diff --git a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java index b3313dd45e8..8cd9f940c61 100644 --- a/api/src/main/java/com/alibaba/nacos/api/common/Constants.java +++ b/api/src/main/java/com/alibaba/nacos/api/common/Constants.java @@ -35,6 +35,8 @@ public class Constants { public static final String CLIENT_VERSION_KEY = "ClientVersion"; + public static final String CLIENT_IP = "ClientIp"; + public static final String UNKNOWN_APP = "UnknownApp"; public static final String DEFAULT_DOMAINNAME = "commonconfig.config-host.taobao.com"; diff --git a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java index c9dab7288f6..557dc29c286 100644 --- a/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java +++ b/api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java @@ -25,14 +25,16 @@ * @version $Id: ConfigChangeClusterSyncRequest.java, v 0.1 2020年08月11日 4:30 PM liuzunfei Exp $ */ public class ConfigChangeClusterSyncRequest extends AbstractConfigRequest { - - String tag; - + long lastModified; + String grayName; + + @Deprecated boolean isBeta; - boolean isBatch; + @Deprecated + String tag; public boolean isBeta() { return isBeta; @@ -42,14 +44,6 @@ public void setBeta(boolean beta) { isBeta = beta; } - public boolean isBatch() { - return isBatch; - } - - public void setBatch(boolean batch) { - isBatch = batch; - } - /** * Getter method for property tag. * @@ -68,6 +62,14 @@ public void setTag(String tag) { this.tag = tag; } + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + /** * Getter method for property lastModified. * diff --git a/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java b/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java index 075c0b1b637..4ee3ee2e188 100644 --- a/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java +++ b/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java @@ -90,6 +90,26 @@ public enum ErrorCode { */ PARAMETER_MISMATCH(20009, "parameter mismatch"), + /** + * config gray request error. + */ + CONFIG_GRAY_OVER_MAX_VERSION_COUNT(20010, "config gray version version over max count"), + + /** + * config gray tag v2 rule format invalid. + */ + CONFIG_GRAY_RULE_FORMAT_INVALID(20011, "config gray rule format invalid"), + + /** + * config gray tag v2 rule version invalid. + */ + CONFIG_GRAY_VERSION_INVALID(20012, "config gray rule version invalid"), + + /** + * config gray request error. + */ + CONFIG_GRAY_NAME_UNRECOGNIZED_ERROR(20013, "config gray name not recognized"), + /** * service name error. */ diff --git a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java index c633f893484..221e90cb7df 100644 --- a/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java +++ b/api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java @@ -18,9 +18,11 @@ import com.alibaba.nacos.api.ability.constant.AbilityKey; import com.alibaba.nacos.api.ability.constant.AbilityStatus; +import com.alibaba.nacos.api.common.Constants; import java.util.HashMap; import java.util.Map; +import java.util.Objects; /** * RequestMeta info. @@ -38,6 +40,8 @@ public class RequestMeta { private Map labels = new HashMap<>(); + private Map appLabels = new HashMap<>(); + private Map abilityTable; public AbilityStatus getConnectionAbility(AbilityKey abilityKey) { @@ -90,6 +94,35 @@ public Map getLabels() { */ public void setLabels(Map labels) { this.labels = labels; + extractAppLabels(); + } + + private void extractAppLabels() { + HashMap applabelsMap = new HashMap(8) { + { + put(Constants.APPNAME, labels.get(Constants.APPNAME)); + put(Constants.CLIENT_VERSION_KEY, clientVersion); + put(Constants.CLIENT_IP, clientIp); + } + }; + labels.entrySet().stream().filter(Objects::nonNull).filter(e -> e.getKey().startsWith(Constants.APP_CONN_PREFIX) + && e.getKey().length() > Constants.APP_CONN_PREFIX.length() && !e.getValue().trim().isEmpty()) + .forEach(entry -> { + applabelsMap.putIfAbsent(entry.getKey().substring(Constants.APP_CONN_PREFIX.length()), + entry.getValue()); + }); + this.appLabels = applabelsMap; + } + + /** + * get labels map with filter of starting with prefix #{@link Constants#APP_CONN_PREFIX} and return a new map trim + * the prefix #{@link Constants#APP_CONN_PREFIX}. + * + * @return map of labels. + * @date 2024/2/29 + */ + public Map getAppLabels() { + return appLabels; } /** diff --git a/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java b/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java index d1055c18c73..6562f54dee7 100644 --- a/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java +++ b/api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java @@ -40,7 +40,6 @@ void before() { configChangeClusterSyncRequest.setTag(TAG); configChangeClusterSyncRequest.setBeta(Boolean.TRUE); configChangeClusterSyncRequest.setLastModified(0L); - configChangeClusterSyncRequest.setBatch(false); configChangeClusterSyncRequest.putAllHeader(HEADERS); requestId = injectRequestUuId(configChangeClusterSyncRequest); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java b/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java index 889d58fd504..9e558c13809 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java @@ -292,6 +292,17 @@ public class Constants { public static final String CONFIG_SEARCH_ACCURATE = "accurate"; + /** + * Gray rule. + */ + public static final String GRAY_RULE_TYPE = "type"; + + public static final String GRAY_RULE_EXPR = "expr"; + + public static final String GRAY_RULE_VERSION = "version"; + + public static final String GRAY_RULE_PRIORITY = "priority"; + /** * default nacos encode. */ @@ -299,6 +310,13 @@ public class Constants { public static final String NACOS_PERSIST_ENCODE_KEY = "nacosPersistEncodingKey"; + /** + * config publish type. + */ + public static final String FORMAL = "formal"; + + public static final String GRAY = "gray"; + static String getPersistEncode() { String persistEncode = System.getenv(NACOS_PERSIST_ENCODE_KEY); if (StringUtils.isBlank(persistEncode)) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/constant/PropertiesConstant.java b/config/src/main/java/com/alibaba/nacos/config/server/constant/PropertiesConstant.java index 29ab7f38325..309d36b6de7 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/constant/PropertiesConstant.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/constant/PropertiesConstant.java @@ -64,5 +64,7 @@ public class PropertiesConstant { public static final String DUMP_CHANGE_WORKER_INTERVAL = "dumpChangeWorkerInterval"; public static final String CONFIG_RENTENTION_DAYS = "nacos.config.retention.days"; - + + public static final String GRAY_CAPATIBEL_MODEL = "nacos.config.gray.compatible.model"; + } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java index 938d07b8078..b221ce47ec1 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @@ -32,6 +32,7 @@ import com.alibaba.nacos.config.server.model.ConfigAllInfo; import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.ConfigInfo4Beta; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; import com.alibaba.nacos.config.server.model.ConfigMetadata; import com.alibaba.nacos.config.server.model.ConfigRequestInfo; import com.alibaba.nacos.config.server.model.GroupkeyListenserStatus; @@ -39,6 +40,8 @@ import com.alibaba.nacos.config.server.model.SampleResult; import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; import com.alibaba.nacos.config.server.model.form.ConfigForm; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; import com.alibaba.nacos.config.server.monitor.MetricsMonitor; import com.alibaba.nacos.config.server.paramcheck.ConfigBlurSearchHttpParamExtractor; import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor; @@ -48,11 +51,13 @@ import com.alibaba.nacos.config.server.service.ConfigOperationService; import com.alibaba.nacos.config.server.service.ConfigSubService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import com.alibaba.nacos.config.server.utils.GroupKey; import com.alibaba.nacos.config.server.utils.MD5Util; import com.alibaba.nacos.config.server.utils.ParamUtils; +import com.alibaba.nacos.config.server.utils.PropertyUtil; import com.alibaba.nacos.config.server.utils.RequestUtil; import com.alibaba.nacos.config.server.utils.TimeUtils; import com.alibaba.nacos.config.server.utils.YamlParserUtil; @@ -69,6 +74,7 @@ import com.alibaba.nacos.sys.utils.InetUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -124,6 +130,8 @@ public class ConfigController { private ConfigInfoBetaPersistService configInfoBetaPersistService; + private ConfigInfoGrayPersistService configInfoGrayPersistService; + private NamespacePersistService namespacePersistService; private final ConfigOperationService configOperationService; @@ -132,14 +140,15 @@ public class ConfigController { public ConfigController(ConfigServletInner inner, ConfigOperationService configOperationService, ConfigSubService configSubService, ConfigInfoPersistService configInfoPersistService, - NamespacePersistService namespacePersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService) { + NamespacePersistService namespacePersistService, ConfigInfoBetaPersistService configInfoBetaPersistService, + ConfigInfoGrayPersistService configInfoGrayPersistService) { this.inner = inner; this.configOperationService = configOperationService; this.configSubService = configSubService; this.configInfoPersistService = configInfoPersistService; this.namespacePersistService = namespacePersistService; this.configInfoBetaPersistService = configInfoBetaPersistService; + this.configInfoGrayPersistService = configInfoGrayPersistService; } /** @@ -198,7 +207,6 @@ public Boolean publishConfig(HttpServletRequest request, HttpServletResponse res configForm.setEffect(effect); configForm.setType(type); configForm.setSchema(schema); - if (StringUtils.isBlank(srcUser)) { configForm.setSrcUser(RequestUtil.getSrcUserName(request)); } @@ -315,14 +323,14 @@ public RestResult deleteConfigs(HttpServletRequest request, @RequestPar String clientIp = RequestUtil.getRemoteIp(request); String srcUser = RequestUtil.getSrcUserName(request); final Timestamp time = TimeUtils.getCurrentTime(); - List configInfoList = configInfoPersistService.removeConfigInfoByIds(ids, clientIp, srcUser); + List configInfoList = configInfoPersistService.removeConfigInfoByIds(ids, clientIp, srcUser); if (CollectionUtils.isEmpty(configInfoList)) { return RestResultUtils.success(true); } - for (ConfigInfo configInfo : configInfoList) { + for (ConfigAllInfo configInfo : configInfoList) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configInfo.getDataId(), configInfo.getGroup(), - configInfo.getTenant(), time.getTime())); + new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), + time.getTime())); ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), null, time.getTime(), clientIp, ConfigTraceService.PERSISTENCE_EVENT, @@ -431,8 +439,8 @@ public Page fuzzySearchConfig(@RequestParam("dataId") String dataId, @RequestParam("group") String group, @RequestParam(value = "appName", required = false) String appName, @RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant, @RequestParam(value = "config_tags", required = false) String configTags, - @RequestParam(value = "types", required = false) String types, - @RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize) { + @RequestParam(value = "types", required = false) String types, @RequestParam("pageNo") int pageNo, + @RequestParam("pageSize") int pageSize) { MetricsMonitor.getFuzzySearchMonitor().incrementAndGet(); Map configAdvanceInfo = new HashMap<>(50); if (StringUtils.isNotBlank(appName)) { @@ -471,15 +479,20 @@ public RestResult stopBeta(HttpServletRequest httpServletRequest, String remoteIp = getRemoteIp(httpServletRequest); String requestIpApp = RequestUtil.getAppName(httpServletRequest); try { - configInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, tenant); + configInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, BetaGrayRule.TYPE_BETA, remoteIp, + RequestUtil.getSrcUserName(httpServletRequest)); } catch (Throwable e) { LOGGER.error("remove beta data error", e); return RestResultUtils.failed(500, false, "remove beta data error"); } ConfigTraceService.logPersistenceEvent(dataId, group, tenant, requestIpApp, System.currentTimeMillis(), remoteIp, ConfigTraceService.PERSISTENCE_EVENT_BETA, ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null); + + if (PropertyUtil.isGrayCompatibleModel()) { + configInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, tenant); + } ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(true, dataId, group, tenant, System.currentTimeMillis())); + new ConfigDataChangeEvent(dataId, group, tenant, BetaGrayRule.TYPE_BETA, System.currentTimeMillis())); return RestResultUtils.success("stop beta ok", true); } @@ -499,14 +512,21 @@ public RestResult queryBeta(@RequestParam(value = "dataId") Str @RequestParam(value = "group") String group, @RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant) { try { - ConfigInfo4Beta ci = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant); - if (Objects.nonNull(ci)) { - String encryptedDataKey = ci.getEncryptedDataKey(); - Pair pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, ci.getContent()); - ci.setContent(pair.getSecond()); + ConfigInfo4Beta configInfo4Beta = null; + ConfigInfoGrayWrapper beta4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant, + "beta"); + if (Objects.nonNull(beta4Gray)) { + String encryptedDataKey = beta4Gray.getEncryptedDataKey(); + Pair pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, + beta4Gray.getContent()); + beta4Gray.setContent(pair.getSecond()); + configInfo4Beta = new ConfigInfo4Beta(); + BeanUtils.copyProperties(beta4Gray, configInfo4Beta); + configInfo4Beta.setBetaIps( + GrayRuleManager.deserializeConfigGrayPersistInfo(beta4Gray.getGrayRule()).getExpr()); } - return RestResultUtils.success("query beta ok", ci); + return RestResultUtils.success("query beta ok", configInfo4Beta); } catch (Throwable e) { LOGGER.error("query beta data error", e); return RestResultUtils.failed("query beta data error"); @@ -683,8 +703,8 @@ public RestResult> importAndPublishConfig(HttpServletRequest null, policy); for (ConfigInfo configInfo : configInfoList) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configInfo.getDataId(), configInfo.getGroup(), - configInfo.getTenant(), time.getTime())); + new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), + time.getTime())); ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB, @@ -936,8 +956,8 @@ public RestResult> cloneConfig(HttpServletRequest request, srcIp, null, policy); for (ConfigInfo configInfo : configInfoList4Clone) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configInfo.getDataId(), configInfo.getGroup(), - configInfo.getTenant(), time.getTime())); + new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), + time.getTime())); ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB, diff --git a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java index 4accddd06b4..f5c94e66265 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java @@ -26,7 +26,9 @@ import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.enums.FileTypeEnum; import com.alibaba.nacos.config.server.model.CacheItem; -import com.alibaba.nacos.config.server.model.ConfigCache; +import com.alibaba.nacos.config.server.model.ConfigCacheGray; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.LongPollingService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; @@ -49,6 +51,7 @@ import java.io.PrintWriter; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -149,9 +152,6 @@ public String doGetConfig(HttpServletRequest request, HttpServletResponse respon if (lockResult > 0 && cacheItem != null) { try { long lastModified; - boolean isBeta = - cacheItem.isBeta() && cacheItem.getConfigCacheBeta() != null && cacheItem.getIps4Beta() != null - && cacheItem.getIps4Beta().contains(clientIp); final String configType = (null != cacheItem.getType()) ? cacheItem.getType() : FileTypeEnum.TEXT.getFileType(); @@ -160,46 +160,62 @@ public String doGetConfig(HttpServletRequest request, HttpServletResponse respon String contentTypeHeader = fileTypeEnum.getContentType(); response.setHeader(HttpHeaderConsts.CONTENT_TYPE, isV2 ? MediaType.APPLICATION_JSON : contentTypeHeader); + + ConfigCacheGray matchedGray = null; + Map appLabels = new HashMap(4); + appLabels.put(BetaGrayRule.CLIENT_IP_LABEL, clientIp); + boolean specificTag = StringUtils.isNotBlank(tag); + + if (specificTag) { + appLabels.put(TagGrayRule.VIP_SERVER_TAG_LABEL, tag); + } else if (StringUtils.isNotBlank(autoTag)) { + appLabels.put(TagGrayRule.VIP_SERVER_TAG_LABEL, autoTag); + } + + if (cacheItem.getSortConfigGrays() != null && !cacheItem.getSortConfigGrays().isEmpty()) { + for (ConfigCacheGray configCacheGray : cacheItem.getSortConfigGrays()) { + if (configCacheGray.match(appLabels)) { + matchedGray = configCacheGray; + break; + } + } + } + String pullEvent; String content; String md5; String encryptedDataKey; - if (isBeta) { - ConfigCache configCacheBeta = cacheItem.getConfigCacheBeta(); - pullEvent = ConfigTraceService.PULL_EVENT_BETA; - md5 = configCacheBeta.getMd5(acceptCharset); - lastModified = configCacheBeta.getLastModifiedTs(); - encryptedDataKey = configCacheBeta.getEncryptedDataKey(); - content = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant); - response.setHeader("isBeta", "true"); - } else { - if (StringUtils.isBlank(tag)) { - if (isUseTag(cacheItem, autoTag)) { - - ConfigCache configCacheTag = cacheItem.getConfigCacheTags().get(autoTag); - md5 = configCacheTag.getMd5(acceptCharset); - lastModified = configCacheTag.getLastModifiedTs(); - encryptedDataKey = configCacheTag.getEncryptedDataKey(); - content = ConfigDiskServiceFactory.getInstance() - .getTagContent(dataId, group, tenant, autoTag); - pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + autoTag; - response.setHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG, - URLEncoder.encode(autoTag, StandardCharsets.UTF_8.displayName())); - } else { - pullEvent = ConfigTraceService.PULL_EVENT; - md5 = cacheItem.getConfigCache().getMd5(acceptCharset); - lastModified = cacheItem.getConfigCache().getLastModifiedTs(); - encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey(); - content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant); - } - } else { - md5 = cacheItem.getTagMd5(tag, acceptCharset); - lastModified = cacheItem.getTagLastModified(tag); - encryptedDataKey = cacheItem.getTagEncryptedDataKey(tag); - - content = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag); - pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + tag; + + if (matchedGray != null) { + md5 = matchedGray.getMd5(acceptCharset); + lastModified = matchedGray.getLastModifiedTs(); + encryptedDataKey = matchedGray.getEncryptedDataKey(); + content = ConfigDiskServiceFactory.getInstance() + .getGrayContent(dataId, group, tenant, matchedGray.getGrayName()); + pullEvent = ConfigTraceService.PULL_EVENT + "-" + matchedGray.getGrayName(); + if (BetaGrayRule.TYPE_BETA.equals(matchedGray.getGrayName())) { + response.setHeader("isBeta", "true"); + } + if (TagGrayRule.TYPE_TAG.equals(matchedGray.getGrayRule().getType())) { + response.setHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG, + URLEncoder.encode(matchedGray.getGrayRule().getRawGrayRuleExp(), + StandardCharsets.UTF_8.displayName())); } + } else if (specificTag) { + //specific tag is not found + md5 = null; + lastModified = 0L; + encryptedDataKey = null; + content = null; + pullEvent = ConfigTraceService.PULL_EVENT + "-" + TagGrayRule.TYPE_TAG + "-" + tag; + response.setHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG, + URLEncoder.encode(tag, StandardCharsets.UTF_8.displayName())); + } else { + md5 = cacheItem.getConfigCache().getMd5(acceptCharset); + lastModified = cacheItem.getConfigCache().getLastModifiedTs(); + encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey(); + content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant); + pullEvent = ConfigTraceService.PULL_EVENT; } if (content == null) { @@ -276,10 +292,4 @@ private String get409Result(HttpServletResponse response, boolean isV2) throws I } return HttpServletResponse.SC_CONFLICT + ""; } - - private static boolean isUseTag(CacheItem cacheItem, String tag) { - return cacheItem != null && cacheItem.getConfigCacheTags() != null && cacheItem.getConfigCacheTags() - .containsKey(tag); - } - } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java b/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java index 3721a8b34ca..e0423f3daa7 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java @@ -19,10 +19,10 @@ import com.alibaba.nacos.config.server.utils.SimpleReadWriteLock; import com.alibaba.nacos.core.utils.StringPool; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * Cache item. @@ -30,198 +30,102 @@ * @author Nacos */ public class CacheItem { - + final String groupKey; - + public String type; - + ConfigCache configCache = new ConfigCache(); - - /** - * Use for beta. - */ - public volatile boolean isBeta = false; - - public volatile List ips4Beta; - - ConfigCache configCacheBeta = null; - - /** - * Use for batch. - */ - public volatile boolean isBatch = false; - - public volatile int delimiter = 0; - - ConfigCache configCacheBatch = null; - + /** - * Use for tag. + * Use for gray. */ - private volatile Map configCacheTags = null; - + private volatile Map configCacheGray = null; + + List sortedConfigCacheGrayList = null; + private final SimpleReadWriteLock rwLock = new SimpleReadWriteLock(); - + public CacheItem(String groupKey, String encryptedDataKey) { this.groupKey = StringPool.get(groupKey); this.getConfigCache().setEncryptedDataKey(encryptedDataKey); } - + public CacheItem(String groupKey) { this.groupKey = StringPool.get(groupKey); } - + public ConfigCache getConfigCache() { return configCache; } - - public boolean isBeta() { - return isBeta; - } - - public void setBeta(boolean isBeta) { - this.isBeta = isBeta; - } - - /** - * remove beta. - */ - public void removeBeta() { - this.isBeta = false; - this.ips4Beta = null; - configCacheBeta = null; - } - - public List getIps4Beta() { - return ips4Beta; - } - - public void setIps4Beta(List ips4Beta) { - this.ips4Beta = ips4Beta; - } - + public SimpleReadWriteLock getRwLock() { return rwLock; } - + public String getType() { return type; } - + public void setType(String type) { this.type = type; } - + public String getGroupKey() { return groupKey; } - + /** - * init beta cache if empty. + * init config gray if empty. */ - public void initBetaCacheIfEmpty() { - if (this.configCacheBeta == null) { - this.configCacheBeta = new ConfigCache(); - } - if (this.ips4Beta == null) { - this.ips4Beta = new ArrayList<>(); + public void initConfigGrayIfEmpty() { + if (this.configCacheGray == null) { + this.configCacheGray = new HashMap<>(4); } } - + /** - * get config cache beta. + * init config gray if empty. * - * @return + * @param grayName gray name. */ - public ConfigCache getConfigCacheBeta() { - return configCacheBeta; - } - - /** - * init batch cache if empty. - */ - public void initBatchCacheIfEmpty() { - if (this.configCacheBatch == null) { - this.configCacheBatch = new ConfigCache(); + public void initConfigGrayIfEmpty(String grayName) { + initConfigGrayIfEmpty(); + if (!this.configCacheGray.containsKey(grayName)) { + this.configCacheGray.put(grayName, new ConfigCacheGray(grayName)); } } - - public ConfigCache getConfigCacheBatch() { - return configCacheBatch; - } - - /** - * remove batch. - */ - public void removeBatch() { - this.configCacheBatch = null; - this.isBatch = false; - } - - /** - * init config tags if empty. - */ - public void initConfigTagsIfEmpty() { - if (this.getConfigCacheTags() == null) { - this.configCacheTags = new HashMap<>(16); - } + + public List getSortConfigGrays() { + return sortedConfigCacheGrayList; } - + /** - * init config tag if empty. - * - * @param tag tag. + * sort config gray. */ - public void initConfigTagsIfEmpty(String tag) { - initConfigTagsIfEmpty(); - if (!this.configCacheTags.containsKey(tag)) { - this.configCacheTags.put(tag, new ConfigCache()); + public void sortConfigGray() { + if (configCacheGray == null || configCacheGray.isEmpty()) { + sortedConfigCacheGrayList = null; + return; } + + sortedConfigCacheGrayList = configCacheGray.values().stream().sorted((o1, o2) -> { + if (o1.getPriority() != o2.getPriority()) { + return Integer.compare(o1.getPriority(), o2.getPriority()) * -1; + } else { + return o1.getGrayName().compareTo(o2.getGrayName()); + } + + }).collect(Collectors.toList()); } - - public void clearConfigTags() { - this.configCacheTags = null; - } - - public Map getConfigCacheTags() { - return configCacheTags; - } - - public boolean isBatch() { - return isBatch; - } - - public void setBatch(boolean batch) { - isBatch = batch; - } - - public int getDelimiter() { - return delimiter; - } - - public void setDelimiter(int delimiter) { - this.delimiter = delimiter; - } - - public long getTagLastModified(String tag) { - if (configCacheTags == null || !configCacheTags.containsKey(tag)) { - return -1L; - } - return configCacheTags.get(tag).getLastModifiedTs(); - } - - public String getTagEncryptedDataKey(String tag) { - if (configCacheTags == null || !configCacheTags.containsKey(tag)) { - return null; - } - return configCacheTags.get(tag).getEncryptedDataKey(); + + public Map getConfigCacheGray() { + return configCacheGray; } - - public String getTagMd5(String tag, String encode) { - if (configCacheTags == null || !configCacheTags.containsKey(tag)) { - return null; - } - return configCacheTags.get(tag).getMd5(encode); + + public void clearConfigGrays() { + this.configCacheGray = null; + this.sortedConfigCacheGrayList = null; } - + } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java new file mode 100644 index 00000000000..f3c8ccfd700 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java @@ -0,0 +1,117 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model; + +import com.alibaba.nacos.config.server.model.gray.GrayRule; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; + +import java.io.Serializable; +import java.util.Map; + +/** + * extensible config cache. + * + * @author rong + */ +public class ConfigCacheGray extends ConfigCache implements Serializable { + + private String grayName; + + private GrayRule grayRule; + + /** + * clear cache. + */ + @Override + public void clear() { + super.clear(); + } + + public ConfigCacheGray(String grayName) { + this.grayName = grayName; + } + + public GrayRule getGrayRule() { + return grayRule; + } + + public ConfigCacheGray(String md5Gbk, String md5Utf8, long lastModifiedTs, String grayRule) + throws RuntimeException { + super(md5Gbk, md5Utf8, lastModifiedTs); + this.grayRule = GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRule)); + if (this.grayRule == null || !this.grayRule.isValid()) { + throw new RuntimeException("raw gray rule is invalid"); + } + } + + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + + /** + * get raw gray rule from db. + * + * @return raw gray rule from db. + * @date 2024/3/14 + */ + public String getRawGrayRule() { + return grayRule.getRawGrayRuleExp(); + } + + /** + * reset gray rule. + * + * @param grayRule raw gray rule from db. + * @throws RuntimeException if gray rule is invalid. + * @date 2024/3/14 + */ + public void resetGrayRule(String grayRule) throws RuntimeException { + this.grayRule = GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRule)); + if (this.grayRule == null || !this.grayRule.isValid()) { + throw new RuntimeException("raw gray rule is invalid"); + } + } + + /** + * judge whether match gray rule. + * + * @param tags conn tags. + * @return true if match, false otherwise. + * @date 2024/3/14 + */ + public boolean match(Map tags) { + return grayRule.match(tags); + } + + public int getPriority() { + return grayRule.getPriority(); + } + + /** + * if gray rule is valid. + * + * @return true if valid, false otherwise. + * @date 2024/3/14 + */ + public boolean isValid() { + return grayRule != null && grayRule.isValid(); + } +} \ No newline at end of file diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfo.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfo.java index d99505af8a6..957e097f3db 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfo.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfo.java @@ -58,6 +58,10 @@ public class ConfigHistoryInfo implements Serializable { */ private String opType; + private String publishType; + + private String extInfo; + private Timestamp createdTime; private Timestamp lastModifiedTime; @@ -136,6 +140,22 @@ public void setOpType(String opType) { this.opType = opType; } + public String getPublishType() { + return publishType; + } + + public void setPublishType(String publishType) { + this.publishType = publishType; + } + + public String getExtInfo() { + return extInfo; + } + + public void setExtInfo(String extInfo) { + this.extInfo = extInfo; + } + public Timestamp getCreatedTime() { return new Timestamp(createdTime.getTime()); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoGrayWrapper.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoGrayWrapper.java new file mode 100644 index 00000000000..71ef60989a5 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoGrayWrapper.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model; + +/** + * ConfigInfoGrayWrapper. + * + * @author rong + */ +public class ConfigInfoGrayWrapper extends ConfigInfo { + + private static final long serialVersionUID = 4511997591465712505L; + + private long lastModified; + + private String grayName; + + private String grayRule; + + private String srcUser; + + public ConfigInfoGrayWrapper() { + } + + public long getLastModified() { + return lastModified; + } + + public void setLastModified(long lastModified) { + this.lastModified = lastModified; + } + + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + + public String getGrayRule() { + return grayRule; + } + + public void setGrayRule(String grayRule) { + this.grayRule = grayRule; + } + + public String getSrcUser() { + return srcUser; + } + + public void setSrcUser(String srcUser) { + this.srcUser = srcUser; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return super.equals(obj); + } +} \ No newline at end of file diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoStateWrapper.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoStateWrapper.java index 8bc146cb63f..3fd5e6a7a82 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoStateWrapper.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoStateWrapper.java @@ -38,6 +38,8 @@ public class ConfigInfoStateWrapper implements Serializable { private String md5; + private String grayName; + public long getId() { return id; } @@ -78,6 +80,14 @@ public void setTenant(String tenant) { this.tenant = tenant; } + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDataChangeEvent.java b/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDataChangeEvent.java index 7ee4cb192fe..e3f6eb2ebeb 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDataChangeEvent.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDataChangeEvent.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.config.server.model.event; import com.alibaba.nacos.common.notify.Event; -import com.alibaba.nacos.common.utils.StringUtils; /** * ConfigDataChangeEvent. @@ -26,66 +25,29 @@ */ public class ConfigDataChangeEvent extends Event { - public final boolean isBeta; + public String dataId; - public final boolean isBatch; + public String group; - public final String dataId; + public String tenant; - public final String group; - - public final String tenant; - - public final String tag; + public String grayName; public final long lastModifiedTs; - public ConfigDataChangeEvent(String dataId, String group, long gmtModified) { - this(false, dataId, group, gmtModified); - } - - public ConfigDataChangeEvent(boolean isBeta, String dataId, String group, String tenant, long gmtModified) { + public ConfigDataChangeEvent(String dataId, String group, String tenant, long gmtModified) { if (null == dataId || null == group) { throw new IllegalArgumentException("dataId is null or group is null"); } - this.isBeta = isBeta; this.dataId = dataId; this.group = group; this.tenant = tenant; - this.tag = null; - this.isBatch = false; this.lastModifiedTs = gmtModified; } - public ConfigDataChangeEvent(boolean isBeta, String dataId, String group, long gmtModified) { - this(isBeta, dataId, group, StringUtils.EMPTY, gmtModified); - } - - public ConfigDataChangeEvent(boolean isBeta, String dataId, String group, String tenant, String tag, - long gmtModified) { - if (null == dataId || null == group) { - throw new IllegalArgumentException("dataId is null or group is null"); - } - this.isBeta = isBeta; - this.dataId = dataId; - this.group = group; - this.tenant = tenant; - this.tag = tag; - this.isBatch = false; - this.lastModifiedTs = gmtModified; - } - - public ConfigDataChangeEvent(String dataId, String group, String tenant, boolean isBatch, long gmtModified) { - if (null == dataId || null == group) { - throw new IllegalArgumentException(); - } - this.isBeta = false; - this.dataId = dataId; - this.group = group; - this.tenant = tenant; - this.tag = null; - this.isBatch = isBatch; - this.lastModifiedTs = gmtModified; + public ConfigDataChangeEvent(String dataId, String group, String tenant, String grayName, long gmtModified) { + this(dataId, group, tenant, gmtModified); + this.grayName = grayName; } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDumpEvent.java b/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDumpEvent.java index c1ec3b358e3..f9e408fa43f 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDumpEvent.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDumpEvent.java @@ -45,6 +45,10 @@ public class ConfigDumpEvent extends Event { private String tag; + private String grayName; + + private String grayRule; + private String content; private String betaIps; @@ -167,6 +171,22 @@ public void setEncryptedDataKey(String encryptedDataKey) { this.encryptedDataKey = encryptedDataKey; } + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + + public String getGrayRule() { + return grayRule; + } + + public void setGrayRule(String grayRule) { + this.grayRule = grayRule; + } + public static ConfigDumpEventBuilder builder() { return new ConfigDumpEventBuilder(); } @@ -189,6 +209,10 @@ public static final class ConfigDumpEventBuilder { private String tag; + private String grayName; + + private String grayRule; + private String encryptedDataKey; private String content; @@ -239,6 +263,16 @@ public ConfigDumpEventBuilder tag(String tag) { return this; } + public ConfigDumpEventBuilder grayName(String grayName) { + this.grayName = grayName; + return this; + } + + public ConfigDumpEventBuilder grayRule(String grayRule) { + this.grayRule = grayRule; + return this; + } + public ConfigDumpEventBuilder content(String content) { this.content = content; return this; @@ -294,6 +328,8 @@ public ConfigDumpEvent build() { configDumpEvent.setBatch(isBatch); configDumpEvent.setDelimiter(delimiter); configDumpEvent.setLastModifiedTs(lastModifiedTs); + configDumpEvent.setGrayName(grayName); + configDumpEvent.setGrayRule(grayRule); configDumpEvent.isBeta = this.isBeta; return configDumpEvent; } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/event/IstioConfigChangeEvent.java b/config/src/main/java/com/alibaba/nacos/config/server/model/event/IstioConfigChangeEvent.java index 282ab4ee54d..ef82632b549 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/event/IstioConfigChangeEvent.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/event/IstioConfigChangeEvent.java @@ -29,36 +29,9 @@ public class IstioConfigChangeEvent extends ConfigDataChangeEvent { public final String type; - public IstioConfigChangeEvent(String dataId, String group, long gmtModified, String content, String type) { - super(dataId, group, gmtModified); - this.content = content; - this.type = type; - } - - public IstioConfigChangeEvent(boolean isBeta, String dataId, String group, String tenant, long gmtModified, - String content, String type) { - super(isBeta, dataId, group, tenant, gmtModified); - this.content = content; - this.type = type; - } - - public IstioConfigChangeEvent(boolean isBeta, String dataId, String group, long gmtModified, String content, + public IstioConfigChangeEvent(String dataId, String group, String tenant, long gmtModified, String content, String type) { - super(isBeta, dataId, group, gmtModified); - this.content = content; - this.type = type; - } - - public IstioConfigChangeEvent(boolean isBeta, String dataId, String group, String tenant, String tag, - long gmtModified, String content, String type) { - super(isBeta, dataId, group, tenant, tag, gmtModified); - this.content = content; - this.type = type; - } - - public IstioConfigChangeEvent(String dataId, String group, String tenant, boolean isBatch, long gmtModified, - String content, String type) { - super(dataId, group, tenant, isBatch, gmtModified); + super(dataId, group, tenant, gmtModified); this.content = content; this.type = type; } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/event/LocalDataChangeEvent.java b/config/src/main/java/com/alibaba/nacos/config/server/model/event/LocalDataChangeEvent.java index 39ac52a71ec..cd2b935291a 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/event/LocalDataChangeEvent.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/event/LocalDataChangeEvent.java @@ -18,8 +18,6 @@ import com.alibaba.nacos.common.notify.Event; -import java.util.List; - /** * LocalDataChangeEvent. * @@ -29,49 +27,8 @@ public class LocalDataChangeEvent extends Event { public final String groupKey; - public final boolean isBeta; - - public final List betaIps; - - public final String tag; - - public final boolean isBatch; - - public final int delimiter; - public LocalDataChangeEvent(String groupKey) { this.groupKey = groupKey; - this.isBeta = false; - this.betaIps = null; - this.tag = null; - this.isBatch = false; - this.delimiter = 0; - } - - public LocalDataChangeEvent(String groupKey, boolean isBeta, List betaIps) { - this.groupKey = groupKey; - this.isBeta = isBeta; - this.betaIps = betaIps; - this.tag = null; - this.isBatch = false; - this.delimiter = 0; - } - - public LocalDataChangeEvent(String groupKey, String tag) { - this.groupKey = groupKey; - this.isBeta = false; - this.betaIps = null; - this.tag = tag; - this.isBatch = false; - this.delimiter = 0; - } - - public LocalDataChangeEvent(String groupKey, boolean isBatch, int delimiter) { - this.groupKey = groupKey; - this.isBeta = false; - this.betaIps = null; - this.tag = null; - this.isBatch = isBatch; - this.delimiter = delimiter; } + } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/form/ConfigForm.java b/config/src/main/java/com/alibaba/nacos/config/server/model/form/ConfigForm.java index afaee391c48..baf9f2273a5 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/form/ConfigForm.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/form/ConfigForm.java @@ -48,6 +48,16 @@ public class ConfigForm implements NacosForm { private String configTags; + private String encryptedDataKey; + + private String grayName; + + private String grayRuleExp; + + private String grayVersion; + + private int grayPriority; + private String desc; private String use; @@ -58,14 +68,11 @@ public class ConfigForm implements NacosForm { private String schema; - private String encryptedDataKey; - public ConfigForm() { } public ConfigForm(String dataId, String group, String namespaceId, String content, String tag, String appName, - String srcUser, String configTags, String desc, String use, String effect, String type, String schema, - String encryptedDataKey) { + String srcUser, String configTags, String desc, String use, String effect, String type, String schema) { this.dataId = dataId; this.group = group; this.namespaceId = namespaceId; @@ -79,7 +86,6 @@ public ConfigForm(String dataId, String group, String namespaceId, String conten this.effect = effect; this.type = type; this.schema = schema; - this.encryptedDataKey = encryptedDataKey; } public String getDataId() { @@ -194,6 +200,38 @@ public void setEncryptedDataKey(String encryptedDataKey) { this.encryptedDataKey = encryptedDataKey; } + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + + public String getGrayRuleExp() { + return grayRuleExp; + } + + public void setGrayRuleExp(String grayRuleExp) { + this.grayRuleExp = grayRuleExp; + } + + public String getGrayVersion() { + return grayVersion; + } + + public void setGrayVersion(String grayVersion) { + this.grayVersion = grayVersion; + } + + public int getGrayPriority() { + return grayPriority; + } + + public void setGrayPriority(int grayPriority) { + this.grayPriority = grayPriority; + } + @Override public void validate() throws NacosApiException { if (StringUtils.isBlank(dataId)) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/gray/AbstractGrayRule.java b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/AbstractGrayRule.java new file mode 100644 index 00000000000..641ea74fab0 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/AbstractGrayRule.java @@ -0,0 +1,98 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model.gray; + +import com.alibaba.nacos.api.exception.NacosException; + +import java.util.Map; + +/** + * Gray rule. type with version determined parse logic. + * + * @author shiyiyue + */ +public abstract class AbstractGrayRule implements GrayRule { + + protected String rawGrayRuleExp; + + protected int priority; + + protected volatile boolean valid = true; + + public AbstractGrayRule() { + } + + public AbstractGrayRule(String rawGrayRuleExp, int priority) { + try { + parse(rawGrayRuleExp); + this.priority = priority; + } catch (NacosException e) { + valid = false; + } + this.rawGrayRuleExp = rawGrayRuleExp; + } + + /** + * parse gray rule. + * + * @param rawGrayRule raw gray rule. + * @throws NacosException if parse failed. + * @date 2024/3/14 + */ + protected abstract void parse(String rawGrayRule) throws NacosException; + + /** + * match gray rule. + * + * @param labels conn labels. + * @return true if match. + * @date 2024/3/14 + */ + public abstract boolean match(Map labels); + + public boolean isValid() { + return valid; + } + + /** + * get type. + * + * @return gray rule type. + * @date 2024/3/14 + */ + public abstract String getType(); + + /** + * get version. + * + * @return gray rule version. + * @date 2024/3/14 + */ + public abstract String getVersion(); + + public String getRawGrayRuleExp() { + return rawGrayRuleExp; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/gray/BetaGrayRule.java b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/BetaGrayRule.java new file mode 100644 index 00000000000..83fc51e411a --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/BetaGrayRule.java @@ -0,0 +1,97 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model.gray; + +import com.alibaba.nacos.api.exception.NacosException; + +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * beta gray rule for beta ips. + * @author shiyiyue1102 + */ +public class BetaGrayRule extends AbstractGrayRule { + + Set betaIps; + + public static final String CLIENT_IP_LABEL = "ClientIp"; + + public static final String TYPE_BETA = "beta"; + + public static final String VERSION = "1.0.0"; + + public static final int PRIORITY = Integer.MAX_VALUE; + + public BetaGrayRule() { + super(); + } + + public BetaGrayRule(String betaIps, int priority) { + super(betaIps, priority); + } + + /** + * parse beta gray rule. + * @param rawGrayRule raw gray rule. + * @throws NacosException exception. + */ + @Override + protected void parse(String rawGrayRule) throws NacosException { + Set betaIps = new HashSet<>(); + String[] ips = rawGrayRule.split(","); + for (String ip : ips) { + betaIps.add(ip); + } + this.betaIps = betaIps; + } + + @Override + + public boolean match(Map labels) { + return labels.containsKey(CLIENT_IP_LABEL) && betaIps.contains(labels.get(CLIENT_IP_LABEL)); + } + + @Override + public String getType() { + return TYPE_BETA; + } + + @Override + public String getVersion() { + return VERSION; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + BetaGrayRule that = (BetaGrayRule) o; + return Objects.equals(betaIps, that.betaIps); + } + + @Override + public int hashCode() { + return Objects.hash(betaIps); + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/gray/ConfigGrayPersistInfo.java b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/ConfigGrayPersistInfo.java new file mode 100644 index 00000000000..fc7d1cdc50c --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/ConfigGrayPersistInfo.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model.gray; + +/** + * description. + * + * @author rong + * @date 2024-03-14 10:57 + */ +public class ConfigGrayPersistInfo { + + private String type; + + private String version; + + private String expr; + + private int priority; + + public ConfigGrayPersistInfo(String type, String version, String expr, int priority) { + this.type = type; + this.version = version; + this.expr = expr; + this.priority = priority; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getExpr() { + return expr; + } + + public void setExpr(String expr) { + this.expr = expr; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRule.java b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRule.java new file mode 100644 index 00000000000..5fa2e48007f --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRule.java @@ -0,0 +1,76 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model.gray; + +import java.util.Map; + +/** + * gray rule. + * + * @author rong + */ +public interface GrayRule { + + /** + * gray rule match labels or not. + * + * @date 2024/3/14 + * @param labels conn labels. + * @return true if match, false otherwise. + */ + boolean match(Map labels); + + /** + * if the gray rule is valid. + * + * @date 2024/3/14 + * @return true if valid, false otherwise. + */ + boolean isValid(); + + /** + * get gray rule type. + * + * @date 2024/3/14 + * @return the gray rule type. + */ + String getType(); + + /** + * get gray rule version. + * + * @date 2024/3/14 + * @return the gray rule version. + */ + String getVersion(); + + /** + * get gray rule priority. + * + * @date 2024/3/14 + * @return the gray rule priority. + */ + int getPriority(); + + /** + * get raw String of gray rule. + * + * @date 2024/3/14 + * @return the raw String of gray rule. + */ + String getRawGrayRuleExp(); +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRuleManager.java b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRuleManager.java new file mode 100644 index 00000000000..7d8fbb72225 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRuleManager.java @@ -0,0 +1,114 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model.gray; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.google.gson.Gson; + +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * GrayRuleManager. + * + * @author zunfei.lzf + */ +public class GrayRuleManager { + + private static final Map> GRAY_RULE_MAP = new ConcurrentHashMap<>(8); + + public static final String SPLIT = "_"; + + static { + Collection grayRuleCollection = NacosServiceLoader.load(GrayRule.class); + for (GrayRule grayRule : grayRuleCollection) { + GRAY_RULE_MAP.put(grayRule.getType() + SPLIT + grayRule.getVersion(), grayRule.getClass()); + } + } + + /** + * get class by type and version. + * + * @param type type. + * @param version version. + * @return class. + * @date 2024/3/14 + */ + public static Class getClassByTypeAndVersion(String type, String version) { + return GRAY_RULE_MAP.get(type + SPLIT + version); + } + + /** + * construct gray rule. + * + * @param configGrayPersistInfo config gray persist info. + * @return gray rule. + * @date 2024/3/14 + */ + public static GrayRule constructGrayRule(ConfigGrayPersistInfo configGrayPersistInfo) { + Class classByTypeAndVersion = getClassByTypeAndVersion(configGrayPersistInfo.getType(), + configGrayPersistInfo.getVersion()); + if (classByTypeAndVersion == null) { + return null; + } + try { + Constructor declaredConstructor = classByTypeAndVersion.getDeclaredConstructor(String.class, int.class); + declaredConstructor.setAccessible(true); + return (GrayRule) declaredConstructor.newInstance(configGrayPersistInfo.getExpr(), + configGrayPersistInfo.getPriority()); + } catch (Exception e) { + throw new RuntimeException(String.format("construct gray rule failed with type[%s], version[%s].", + configGrayPersistInfo.getType(), configGrayPersistInfo.getVersion()), e); + } + } + + /** + * construct config gray persist info. + * + * @param grayRule gray rule. + * @return config gray persist info. + * @date 2024/3/14 + */ + public static ConfigGrayPersistInfo constructConfigGrayPersistInfo(GrayRule grayRule) { + return new ConfigGrayPersistInfo(grayRule.getType(), grayRule.getVersion(), grayRule.getRawGrayRuleExp(), + grayRule.getPriority()); + } + + /** + * deserialize config gray persist info. + * + * @param grayRuleRawStringFromDb gray rule raw string from db. + * @return config gray persist info. + * @date 2024/3/14 + */ + public static ConfigGrayPersistInfo deserializeConfigGrayPersistInfo(String grayRuleRawStringFromDb) { + return (new Gson()).fromJson(grayRuleRawStringFromDb, ConfigGrayPersistInfo.class); + } + + /** + * serialize config gray persist info. + * + * @param configGrayPersistInfo config gray persist info. + * @return serialized string. + * @date 2024/3/14 + */ + public static String serializeConfigGrayPersistInfo(ConfigGrayPersistInfo configGrayPersistInfo) { + return (new Gson()).toJson(configGrayPersistInfo); + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/gray/TagGrayRule.java b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/TagGrayRule.java new file mode 100644 index 00000000000..0f3f845e6ea --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/gray/TagGrayRule.java @@ -0,0 +1,91 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.model.gray; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.utils.StringUtils; + +import java.util.Map; +import java.util.Objects; + +import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; + +/** + * Tag gray rule. + * + * @author shiyiyue + */ +public class TagGrayRule extends AbstractGrayRule { + + String tagValue; + + public static final String VIP_SERVER_TAG_LABEL = VIPSERVER_TAG; + + public static final String TYPE_TAG = "tag"; + + public static final String VERSION = "1.0.0"; + + public static final int PRIORITY = Integer.MAX_VALUE - 1; + + public TagGrayRule() { + super(); + } + + public TagGrayRule(String rawGrayRuleExp, int priority) { + super(rawGrayRuleExp, priority); + } + + @Override + protected void parse(String rawGrayRule) throws NacosException { + if (StringUtils.isBlank(rawGrayRule)) { + return; + } + this.tagValue = rawGrayRule; + } + + @Override + public boolean match(Map labels) { + return labels.containsKey(VIP_SERVER_TAG_LABEL) && tagValue.equals(labels.get(VIP_SERVER_TAG_LABEL)); + } + + @Override + public String getType() { + return TYPE_TAG; + } + + @Override + public String getVersion() { + return VERSION; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TagGrayRule that = (TagGrayRule) o; + return tagValue.equals(that.tagValue); + } + + @Override + public int hashCode() { + return Objects.hash(tagValue); + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandler.java index 4583af292b1..e4e95e9f2eb 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandler.java @@ -58,17 +58,17 @@ public ConfigChangeBatchListenResponse handle(ConfigBatchListenRequest configCha String tag = configChangeListenRequest.getHeader(Constants.VIPSERVER_TAG); ParamUtils.checkParam(tag); ConfigChangeBatchListenResponse configChangeBatchListenResponse = new ConfigChangeBatchListenResponse(); - for (ConfigBatchListenRequest.ConfigListenContext listenContext : configChangeListenRequest - .getConfigListenContexts()) { - String groupKey = GroupKey2 - .getKey(listenContext.getDataId(), listenContext.getGroup(), listenContext.getTenant()); + for (ConfigBatchListenRequest.ConfigListenContext listenContext : configChangeListenRequest.getConfigListenContexts()) { + String groupKey = GroupKey2.getKey(listenContext.getDataId(), listenContext.getGroup(), + listenContext.getTenant()); groupKey = StringPool.get(groupKey); String md5 = StringPool.get(listenContext.getMd5()); if (configChangeListenRequest.isListen()) { configChangeListenContext.addListen(groupKey, md5, connectionId); - boolean isUptoDate = ConfigCacheService.isUptodate(groupKey, md5, meta.getClientIp(), tag); + boolean isUptoDate = ConfigCacheService.isUptodate(groupKey, md5, meta.getClientIp(), tag, + meta.getAppLabels()); if (!isUptoDate) { configChangeBatchListenResponse.addChangeConfig(listenContext.getDataId(), listenContext.getGroup(), listenContext.getTenant()); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java index f354cd759b6..5dd9994c828 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java @@ -21,13 +21,18 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.RemoteConstants; import com.alibaba.nacos.api.remote.request.RequestMeta; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; +import com.alibaba.nacos.config.server.service.ConfigGrayModelMigrateService; import com.alibaba.nacos.config.server.service.dump.DumpRequest; import com.alibaba.nacos.config.server.service.dump.DumpService; import com.alibaba.nacos.config.server.utils.ParamUtils; +import com.alibaba.nacos.config.server.utils.PropertyUtil; +import com.alibaba.nacos.core.control.TpsControl; import com.alibaba.nacos.core.paramcheck.ExtractorManager; import com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor; import com.alibaba.nacos.core.remote.RequestHandler; -import com.alibaba.nacos.core.control.TpsControl; import com.alibaba.nacos.core.remote.grpc.InvokeSource; import org.springframework.stereotype.Component; @@ -44,8 +49,12 @@ public class ConfigChangeClusterSyncRequestHandler private final DumpService dumpService; - public ConfigChangeClusterSyncRequestHandler(DumpService dumpService) { + private ConfigGrayModelMigrateService configGrayModelMigrateService; + + public ConfigChangeClusterSyncRequestHandler(DumpService dumpService, + ConfigGrayModelMigrateService configGrayModelMigrateService) { this.dumpService = dumpService; + this.configGrayModelMigrateService = configGrayModelMigrateService; } @TpsControl(pointName = "ClusterConfigChangeNotify") @@ -53,15 +62,45 @@ public ConfigChangeClusterSyncRequestHandler(DumpService dumpService) { @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class) public ConfigChangeClusterSyncResponse handle(ConfigChangeClusterSyncRequest configChangeSyncRequest, RequestMeta meta) throws NacosException { + + checkCompatity(configChangeSyncRequest); + ParamUtils.checkParam(configChangeSyncRequest.getTag()); DumpRequest dumpRequest = DumpRequest.create(configChangeSyncRequest.getDataId(), configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(), configChangeSyncRequest.getLastModified(), meta.getClientIp()); - dumpRequest.setBeta(configChangeSyncRequest.isBeta()); - dumpRequest.setBatch(configChangeSyncRequest.isBatch()); - dumpRequest.setTag(configChangeSyncRequest.getTag()); + + dumpRequest.setGrayName(configChangeSyncRequest.getGrayName()); dumpService.dump(dumpRequest); return new ConfigChangeClusterSyncResponse(); } + /** + * if notified from old server,try to migrate and transfer gray model. + * + * @param configChangeSyncRequest request. + * @return + */ + private void checkCompatity(ConfigChangeClusterSyncRequest configChangeSyncRequest) { + if (PropertyUtil.isGrayCompatibleModel() && StringUtils.isBlank(configChangeSyncRequest.getGrayName())) { + if (configChangeSyncRequest.isBeta() || StringUtils.isNotBlank(configChangeSyncRequest.getTag())) { + + String grayName = null; + //from old server ,beta or tag persist into old model,try migrate and transfer gray model. + if (configChangeSyncRequest.isBeta()) { + configGrayModelMigrateService.checkMigrateBeta(configChangeSyncRequest.getDataId(), + configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant()); + grayName = BetaGrayRule.TYPE_BETA; + } else { + configGrayModelMigrateService.checkMigrateTag(configChangeSyncRequest.getDataId(), + configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(), + configChangeSyncRequest.getTag()); + grayName = TagGrayRule.TYPE_TAG + "_" + configChangeSyncRequest.getTag(); + } + configChangeSyncRequest.setGrayName(grayName); + + } + } + } + } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandler.java index 82ca984b97d..83af673362b 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandler.java @@ -16,23 +16,20 @@ package com.alibaba.nacos.config.server.remote; +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest; import com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse; import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.api.NacosApiException; import com.alibaba.nacos.api.remote.request.RequestMeta; import com.alibaba.nacos.api.remote.response.ResponseCode; import com.alibaba.nacos.auth.annotation.Secured; -import com.alibaba.nacos.common.utils.MapUtil; +import com.alibaba.nacos.common.utils.Pair; import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.model.ConfigInfo; -import com.alibaba.nacos.config.server.model.ConfigOperateResult; -import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; -import com.alibaba.nacos.config.server.service.AggrWhitelist; -import com.alibaba.nacos.config.server.service.ConfigChangePublisher; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; -import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; +import com.alibaba.nacos.config.server.model.ConfigRequestInfo; +import com.alibaba.nacos.config.server.model.form.ConfigForm; +import com.alibaba.nacos.config.server.service.ConfigOperationService; import com.alibaba.nacos.config.server.utils.ParamUtils; import com.alibaba.nacos.core.control.TpsControl; import com.alibaba.nacos.core.paramcheck.ExtractorManager; @@ -41,11 +38,9 @@ import com.alibaba.nacos.core.utils.Loggers; import com.alibaba.nacos.plugin.auth.constant.ActionTypes; import com.alibaba.nacos.plugin.auth.constant.SignType; +import com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.Map; - /** * request handler to publish config. * @@ -55,18 +50,10 @@ @Component public class ConfigPublishRequestHandler extends RequestHandler { - private final ConfigInfoPersistService configInfoPersistService; - - private final ConfigInfoTagPersistService configInfoTagPersistService; + private ConfigOperationService configOperationService; - private final ConfigInfoBetaPersistService configInfoBetaPersistService; - - public ConfigPublishRequestHandler(ConfigInfoPersistService configInfoPersistService, - ConfigInfoTagPersistService configInfoTagPersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService) { - this.configInfoPersistService = configInfoPersistService; - this.configInfoTagPersistService = configInfoTagPersistService; - this.configInfoBetaPersistService = configInfoBetaPersistService; + public ConfigPublishRequestHandler(ConfigOperationService configOperationService) { + this.configOperationService = configOperationService; } @Override @@ -82,7 +69,6 @@ public ConfigPublishResponse handle(ConfigPublishRequest request, RequestMeta me final String tenant = request.getTenant(); final String srcIp = meta.getClientIp(); - final String requestIpApp = request.getAdditionParam("requestIpApp"); final String tag = request.getAdditionParam("tag"); final String appName = request.getAdditionParam("appName"); final String type = request.getAdditionParam("type"); @@ -92,82 +78,49 @@ public ConfigPublishResponse handle(ConfigPublishRequest request, RequestMeta me // check tenant ParamUtils.checkParam(dataId, group, "datumId", content); ParamUtils.checkParam(tag); - Map configAdvanceInfo = new HashMap<>(10); - MapUtil.putIfValNoNull(configAdvanceInfo, "config_tags", request.getAdditionParam("config_tags")); - MapUtil.putIfValNoNull(configAdvanceInfo, "desc", request.getAdditionParam("desc")); - MapUtil.putIfValNoNull(configAdvanceInfo, "use", request.getAdditionParam("use")); - MapUtil.putIfValNoNull(configAdvanceInfo, "effect", request.getAdditionParam("effect")); - MapUtil.putIfValNoNull(configAdvanceInfo, "type", type); - MapUtil.putIfValNoNull(configAdvanceInfo, "schema", request.getAdditionParam("schema")); - ParamUtils.checkParam(configAdvanceInfo); - if (AggrWhitelist.isAggrDataId(dataId)) { - Loggers.REMOTE_DIGEST.warn("[aggr-conflict] {} attempt to publish single data, {}, {}", srcIp, dataId, - group); - throw new NacosException(NacosException.NO_RIGHT, "dataId:" + dataId + " is aggr"); + ConfigForm configForm = new ConfigForm(); + configForm.setDataId(dataId); + configForm.setGroup(group); + configForm.setNamespaceId(tenant); + configForm.setContent(content); + configForm.setTag(tag); + configForm.setAppName(appName); + configForm.setSrcUser(srcUser); + configForm.setConfigTags(request.getAdditionParam("config_tags")); + configForm.setDesc(request.getAdditionParam("desc")); + configForm.setUse(request.getAdditionParam("use")); + configForm.setEffect(request.getAdditionParam("effect")); + configForm.setType(type); + configForm.setSchema(request.getAdditionParam("schema")); + + if (!ConfigType.isValidType(type)) { + configForm.setType(ConfigType.getDefaultType().getType()); } - ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); - configInfo.setMd5(request.getCasMd5()); - configInfo.setType(type); - configInfo.setEncryptedDataKey(encryptedDataKey); - String betaIps = request.getAdditionParam("betaIps"); - ConfigOperateResult configOperateResult = null; - String persistEvent = ConfigTraceService.PERSISTENCE_EVENT; - if (StringUtils.isBlank(betaIps)) { - if (StringUtils.isBlank(tag)) { - if (StringUtils.isNotBlank(request.getCasMd5())) { - configOperateResult = configInfoPersistService.insertOrUpdateCas(srcIp, srcUser, configInfo, - configAdvanceInfo); - if (!configOperateResult.isSuccess()) { - return ConfigPublishResponse.buildFailResponse(ResponseCode.FAIL.getCode(), - "Cas publish fail,server md5 may have changed."); - } - } else { - configOperateResult = configInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, - configAdvanceInfo); - } - ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(false, dataId, group, tenant, - configOperateResult.getLastModified())); - } else { - if (StringUtils.isNotBlank(request.getCasMd5())) { - configOperateResult = configInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, - srcUser); - if (!configOperateResult.isSuccess()) { - return ConfigPublishResponse.buildFailResponse(ResponseCode.FAIL.getCode(), - "Cas publish tag config fail,server md5 may have changed."); - } - } else { - configOperateResult = configInfoTagPersistService.insertOrUpdateTag(configInfo, tag, srcIp, - srcUser); - } - persistEvent = ConfigTraceService.PERSISTENCE_EVENT_TAG + "-" + tag; - ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, dataId, group, tenant, tag, - configOperateResult.getLastModified())); - } + ConfigRequestInfo configRequestInfo = new ConfigRequestInfo(); + configRequestInfo.setSrcIp(srcIp); + configRequestInfo.setRequestIpApp(meta.getLabels().get(Constants.APPNAME)); + configRequestInfo.setBetaIps(request.getAdditionParam("betaIps")); + configRequestInfo.setCasMd5(request.getCasMd5()); + + String encryptedDataKeyFinal = null; + if (StringUtils.isNotBlank(encryptedDataKey)) { + encryptedDataKeyFinal = encryptedDataKey; } else { - // beta publish - if (StringUtils.isNotBlank(request.getCasMd5())) { - configOperateResult = configInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp, - srcUser); - if (!configOperateResult.isSuccess()) { - return ConfigPublishResponse.buildFailResponse(ResponseCode.FAIL.getCode(), - "Cas publish beta config fail,server md5 may have changed."); - } - } else { - configOperateResult = configInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, - srcUser); - } - persistEvent = ConfigTraceService.PERSISTENCE_EVENT_BETA; - - ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(true, dataId, group, tenant, configOperateResult.getLastModified())); + Pair pair = EncryptionHandler.encryptHandler(dataId, content); + content = pair.getSecond(); + encryptedDataKeyFinal = pair.getFirst(); + configForm.setContent(content); + } + try { + configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKeyFinal); + return ConfigPublishResponse.buildSuccessResponse(); + } catch (NacosApiException nacosApiException) { + return ConfigPublishResponse.buildFailResponse(ResponseCode.FAIL.getCode(), + nacosApiException.getErrMsg()); } - ConfigTraceService.logPersistenceEvent(dataId, group, tenant, requestIpApp, - configOperateResult.getLastModified(), srcIp, persistEvent, ConfigTraceService.PERSISTENCE_TYPE_PUB, - content); - return ConfigPublishResponse.buildSuccessResponse(); + } catch (Exception e) { Loggers.REMOTE_DIGEST.error("[ConfigPublishRequestHandler] publish config error ,request ={}", request, e); return ConfigPublishResponse.buildFailResponse( diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java index 902da8ee5a7..7b0d4d88f69 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java @@ -24,6 +24,9 @@ import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.model.CacheItem; +import com.alibaba.nacos.config.server.model.ConfigCacheGray; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; @@ -40,7 +43,10 @@ import org.springframework.stereotype.Component; import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; +import static com.alibaba.nacos.api.common.Constants.CLIENT_IP; import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; import static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG; import static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_HEADER; @@ -81,11 +87,9 @@ private ConfigQueryResponse getContext(ConfigQueryRequest configQueryRequest, Re String groupKey = GroupKey2.getKey(configQueryRequest.getDataId(), configQueryRequest.getGroup(), configQueryRequest.getTenant()); - String autoTag = configQueryRequest.getHeader(com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG); String requestIpApp = meta.getLabels().get(CLIENT_APPNAME_HEADER); String acceptCharset = ENCODE_UTF8; ParamUtils.checkParam(tag); - ParamUtils.checkParam(autoTag); int lockResult = ConfigCacheService.tryConfigReadLock(groupKey); String pullEvent = ConfigTraceService.PULL_EVENT; String pullType = ConfigTraceService.PULL_TYPE_OK; @@ -96,48 +100,62 @@ private ConfigQueryResponse getContext(ConfigQueryRequest configQueryRequest, Re if (lockResult > 0 && cacheItem != null) { try { long lastModified = 0L; - boolean isBeta = cacheItem.isBeta() && cacheItem.getIps4Beta() != null && cacheItem.getIps4Beta() - .contains(clientIp) && cacheItem.getConfigCacheBeta() != null; String configType = cacheItem.getType(); response.setContentType((null != configType) ? configType : "text"); String content; String md5; String encryptedDataKey; - if (isBeta) { - md5 = cacheItem.getConfigCacheBeta().getMd5(acceptCharset); - lastModified = cacheItem.getConfigCacheBeta().getLastModifiedTs(); - content = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant); - pullEvent = ConfigTraceService.PULL_EVENT_BETA; - encryptedDataKey = cacheItem.getConfigCacheBeta().getEncryptedDataKey(); - response.setBeta(true); + ConfigCacheGray matchedGray = null; + Map appLabels = null; + boolean specificTag = StringUtils.isNotBlank(tag); + if (specificTag) { + appLabels = new HashMap<>(4); + appLabels.put(TagGrayRule.VIP_SERVER_TAG_LABEL, tag); + appLabels.put(CLIENT_IP, clientIp); } else { - if (StringUtils.isBlank(tag)) { - if (isUseTag(cacheItem, autoTag)) { - md5 = cacheItem.getTagMd5(autoTag, acceptCharset); - lastModified = cacheItem.getTagLastModified(autoTag); - encryptedDataKey = cacheItem.getTagEncryptedDataKey(autoTag); - content = ConfigDiskServiceFactory.getInstance() - .getTagContent(dataId, group, tenant, autoTag); - pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + autoTag; - response.setTag(URLEncoder.encode(autoTag, ENCODE_UTF8)); - - } else { - md5 = cacheItem.getConfigCache().getMd5(acceptCharset); - lastModified = cacheItem.getConfigCache().getLastModifiedTs(); - encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey(); - content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant); - pullEvent = ConfigTraceService.PULL_EVENT; + appLabels = new HashMap(meta.getAppLabels()); + if (!appLabels.containsKey(CLIENT_IP)) { + appLabels.put(CLIENT_IP, clientIp); + } + } + + if (cacheItem.getSortConfigGrays() != null && !cacheItem.getSortConfigGrays().isEmpty()) { + for (ConfigCacheGray configCacheGray : cacheItem.getSortConfigGrays()) { + if (configCacheGray.match(appLabels)) { + matchedGray = configCacheGray; + break; } - } else { - md5 = cacheItem.getTagMd5(tag, acceptCharset); - lastModified = cacheItem.getTagLastModified(tag); - encryptedDataKey = cacheItem.getTagEncryptedDataKey(tag); - content = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag); - response.setTag(tag); - pullEvent = ConfigTraceService.PULL_EVENT_TAG + "-" + tag; } } + if (matchedGray != null) { + md5 = matchedGray.getMd5(acceptCharset); + lastModified = matchedGray.getLastModifiedTs(); + encryptedDataKey = matchedGray.getEncryptedDataKey(); + content = ConfigDiskServiceFactory.getInstance() + .getGrayContent(dataId, group, tenant, matchedGray.getGrayName()); + pullEvent = ConfigTraceService.PULL_EVENT + "-" + matchedGray.getGrayName(); + if (BetaGrayRule.TYPE_BETA.equals(matchedGray.getGrayName())) { + response.setBeta(true); + } + if (TagGrayRule.TYPE_TAG.equals(matchedGray.getGrayRule().getType())) { + response.setTag(URLEncoder.encode(matchedGray.getRawGrayRule(), ENCODE_UTF8)); + } + } else if (specificTag) { + //specific tag is not found + md5 = null; + lastModified = 0L; + encryptedDataKey = null; + content = null; + pullEvent = ConfigTraceService.PULL_EVENT + "-" + TagGrayRule.TYPE_TAG + "-" + tag; + response.setTag(tag); + } else { + md5 = cacheItem.getConfigCache().getMd5(acceptCharset); + lastModified = cacheItem.getConfigCache().getLastModifiedTs(); + encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey(); + content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant); + pullEvent = ConfigTraceService.PULL_EVENT; + } response.setMd5(md5); response.setEncryptedDataKey(encryptedDataKey); @@ -172,9 +190,4 @@ private ConfigQueryResponse getContext(ConfigQueryRequest configQueryRequest, Re return response; } - private static boolean isUseTag(CacheItem cacheItem, String tag) { - return StringUtils.isNotBlank(tag) && cacheItem.getConfigCacheTags() != null && cacheItem.getConfigCacheTags() - .containsKey(tag); - } - } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandler.java index 942d779da8c..94e46006d69 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandler.java @@ -23,16 +23,17 @@ import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.service.ConfigChangePublisher; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import com.alibaba.nacos.config.server.utils.ParamUtils; import com.alibaba.nacos.config.server.utils.TimeUtils; +import com.alibaba.nacos.core.control.TpsControl; import com.alibaba.nacos.core.paramcheck.ExtractorManager; import com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor; import com.alibaba.nacos.core.remote.RequestHandler; -import com.alibaba.nacos.core.control.TpsControl; import com.alibaba.nacos.core.utils.Loggers; import com.alibaba.nacos.plugin.auth.constant.ActionTypes; import com.alibaba.nacos.plugin.auth.constant.SignType; @@ -51,12 +52,12 @@ public class ConfigRemoveRequestHandler extends RequestHandler betaIps, String tag) { + public void configDataChanged(String groupKey, String dataId, String group, String tenant) { Set listeners = configChangeListenContext.getListeners(groupKey); if (CollectionUtils.isEmpty(listeners)) { @@ -102,12 +99,6 @@ public void configDataChanged(String groupKey, String dataId, String group, Stri ConnectionMeta metaInfo = connection.getMetaInfo(); String clientIp = metaInfo.getClientIp(); - String clientTag = metaInfo.getTag(); - - //tag check - if (StringUtils.isNotBlank(tag) && !tag.equals(clientTag)) { - continue; - } ConfigChangeNotifyRequest notifyRequest = ConfigChangeNotifyRequest.build(dataId, group, tenant); @@ -122,15 +113,13 @@ public void configDataChanged(String groupKey, String dataId, String group, Stri @Override public void onEvent(LocalDataChangeEvent event) { String groupKey = event.groupKey; - boolean isBeta = event.isBeta; - List betaIps = event.betaIps; + String[] strings = GroupKey.parseKey(groupKey); String dataId = strings[0]; String group = strings[1]; String tenant = strings.length > 2 ? strings[2] : ""; - String tag = event.tag; - configDataChanged(groupKey, dataId, group, tenant, isBeta, betaIps, tag); + configDataChanged(groupKey, dataId, group, tenant); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/AggrWhitelist.java b/config/src/main/java/com/alibaba/nacos/config/server/service/AggrWhitelist.java deleted file mode 100644 index c80bd149555..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/AggrWhitelist.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service; - -import com.alibaba.nacos.common.utils.IoUtils; -import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.utils.RegexParser; - -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Pattern; - -import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG; -import static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG; - -/** - * AggrWhitelist. - * - * @author Nacos - */ -public class AggrWhitelist { - - public static final String AGGRIDS_METADATA = "com.alibaba.nacos.metadata.aggrIDs"; - - static final AtomicReference> AGGR_DATAID_WHITELIST = new AtomicReference<>( - new ArrayList<>()); - - /** - * Judge whether specified dataId includes aggregation white list. - * - * @param dataId dataId string value. - * @return Whether to match aggregation rules. - */ - public static boolean isAggrDataId(String dataId) { - if (null == dataId) { - throw new IllegalArgumentException("dataId is null"); - } - - for (Pattern pattern : AGGR_DATAID_WHITELIST.get()) { - if (pattern.matcher(dataId).matches()) { - return true; - } - } - return false; - } - - /** - * Load aggregation white lists based content parameter value. - * - * @param content content string value. - */ - public static void load(String content) { - if (StringUtils.isBlank(content)) { - FATAL_LOG.warn("aggr dataId whitelist is blank."); - return; - } - DEFAULT_LOG.warn("[aggr-dataIds] {}", content); - - try { - List lines = IoUtils.readLines(new StringReader(content)); - compile(lines); - } catch (Exception ioe) { - DEFAULT_LOG.error("failed to load aggr whitelist, " + ioe, ioe); - } - } - - static void compile(List whitelist) { - List list = new ArrayList<>(whitelist.size()); - - for (String line : whitelist) { - if (!StringUtils.isBlank(line)) { - String regex = RegexParser.regexFormat(line.trim()); - list.add(Pattern.compile(regex)); - } - } - AGGR_DATAID_WHITELIST.set(list); - } - - public static List getWhiteList() { - return AGGR_DATAID_WHITELIST.get(); - } -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java index beb7c6e6181..da9ed9ef5f2 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java @@ -17,26 +17,28 @@ package com.alibaba.nacos.config.server.service; import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.common.utils.InternetAddressUtil; import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.model.CacheItem; import com.alibaba.nacos.config.server.model.ConfigCache; +import com.alibaba.nacos.config.server.model.ConfigCacheGray; import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent; +import com.alibaba.nacos.config.server.model.gray.GrayRule; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.sys.env.EnvUtil; -import com.google.common.collect.Lists; import java.io.IOException; -import java.util.Collections; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static com.alibaba.nacos.api.common.Constants.CLIENT_IP; +import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; +import static com.alibaba.nacos.config.server.constant.Constants.NULL; import static com.alibaba.nacos.config.server.constant.Constants.PERSIST_ENCODE; import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG; import static com.alibaba.nacos.config.server.utils.LogUtil.DUMP_LOG; @@ -171,147 +173,84 @@ public static boolean dump(String dataId, String group, String tenant, String co } /** - * Save config file and update md5 value in cache. + * Save gray config file and update md5 value in cache. * * @param dataId dataId string value. * @param group group string value. * @param tenant tenant string value. + * @param grayName grayName string value. + * @param grayRule grayRule string value. * @param content content string value. * @param lastModifiedTs lastModifiedTs. - * @param betaIps betaIps string value. * @return dumpChange success or not. */ - public static boolean dumpBeta(String dataId, String group, String tenant, String content, long lastModifiedTs, - String betaIps, String encryptedDataKey) { + public static boolean dumpGray(String dataId, String group, String tenant, String grayName, String grayRule, + String content, long lastModifiedTs, String encryptedDataKey) { final String groupKey = GroupKey2.getKey(dataId, group, tenant); makeSure(groupKey, null); final int lockResult = tryWriteLock(groupKey); if (lockResult < 0) { - DUMP_LOG.warn("[dump-beta-error] write lock failed. {}", groupKey); + DUMP_LOG.warn("[dump-gray-error] write lock failed. {}", groupKey); return false; } try { //check timestamp - boolean timestampOutDated = lastModifiedTs < ConfigCacheService.getBetaLastModifiedTs(groupKey); - if (timestampOutDated) { - DUMP_LOG.warn("[dump-beta-ignore] timestamp is outdated,groupKey={}", groupKey); - return true; - } + long localGrayLastModifiedTs = ConfigCacheService.getGrayLastModifiedTs(groupKey, grayName); - boolean timestampUpdated = lastModifiedTs > ConfigCacheService.getBetaLastModifiedTs(groupKey); - - String[] betaIpsArr = betaIps.split(","); - List betaIpList = Lists.newArrayList(betaIpsArr); - String md5 = MD5Utils.md5Hex(content, ENCODE_UTF8); - - //md5 check & update local disk cache. - String localContentBetaMd5 = ConfigCacheService.getContentBetaMd5(groupKey); - boolean md5Changed = !md5.equals(localContentBetaMd5); - if (md5Changed) { - DUMP_LOG.info( - "[dump-beta] md5 changed, update md5 in local disk cache. groupKey={}, newMd5={}, oldMd5={}", - groupKey, md5, localContentBetaMd5); - ConfigDiskServiceFactory.getInstance().saveBetaToDisk(dataId, group, tenant, content); - } - - //md5 , ip list timestamp check and update local jvm cache. - boolean ipListChanged = !betaIpList.equals(ConfigCacheService.getBetaIps(groupKey)); - if (md5Changed) { - DUMP_LOG.info( - "[dump-beta] md5 changed, update md5 & ip list & timestamp in jvm cache. groupKey={}, newMd5={}, oldMd5={},lastModifiedTs={}", - groupKey, md5, localContentBetaMd5, lastModifiedTs); - updateBetaMd5(groupKey, md5, betaIpList, lastModifiedTs, encryptedDataKey); - } else if (ipListChanged) { - DUMP_LOG.warn("[dump-beta] ip list changed, update ip list & timestamp in jvm cache. groupKey={}," - + " newIpList={}, oldIpList={},lastModifiedTs={}", groupKey, betaIpList, - ConfigCacheService.getBetaIps(groupKey), lastModifiedTs); - updateBetaIpList(groupKey, betaIpList, lastModifiedTs); - } else if (timestampUpdated) { - DUMP_LOG.warn( - "[dump-beta] timestamp changed, update timestamp in jvm cache. groupKey={}, newLastModifiedTs={}, oldLastModifiedTs={}", - groupKey, lastModifiedTs, ConfigCacheService.getBetaLastModifiedTs(groupKey)); - updateBetaTimeStamp(groupKey, lastModifiedTs); - } else { - DUMP_LOG.warn( - "[dump-beta-ignore] ignore to save jvm cache, md5 & ip list & timestamp no changed. groupKey={}", - groupKey); - } - return true; - } catch (IOException ioe) { - DUMP_LOG.error("[dump-beta-exception] save disk error. " + groupKey + ", " + ioe.toString(), ioe); - return false; - } finally { - releaseWriteLock(groupKey); - } - } - - /** - * Save config file and update md5 value in cache. - * - * @param dataId dataId string value. - * @param group group string value. - * @param tenant tenant string value. - * @param content content string value. - * @param lastModifiedTs lastModifiedTs. - * @param tag tag string value. - * @return dumpChange success or not. - */ - public static boolean dumpTag(String dataId, String group, String tenant, String tag, String content, - long lastModifiedTs, String encryptedDataKey4Tag) { - final String groupKey = GroupKey2.getKey(dataId, group, tenant); - - makeSure(groupKey, null); - final int lockResult = tryWriteLock(groupKey); - - if (lockResult < 0) { - DUMP_LOG.warn("[dump-tag-error] write lock failed. {}", groupKey); - return false; - } - - try { - - //check timestamp - long localTagLastModifiedTs = ConfigCacheService.getTagLastModifiedTs(groupKey, tag); - - boolean timestampOutdated = lastModifiedTs < localTagLastModifiedTs; + boolean timestampOutdated = lastModifiedTs < localGrayLastModifiedTs; if (timestampOutdated) { - DUMP_LOG.warn("[dump-tag-ignore] timestamp is outdated,groupKey={}", groupKey); + DUMP_LOG.warn("[dump-gray-ignore] timestamp is outdated,groupKey={}", groupKey); return true; } - boolean timestampChanged = lastModifiedTs > localTagLastModifiedTs; + boolean timestampChanged = lastModifiedTs > localGrayLastModifiedTs; final String md5 = MD5Utils.md5Hex(content, ENCODE_UTF8); - String localContentTagMd5 = ConfigCacheService.getContentTagMd5(groupKey, tag); - boolean md5Changed = !md5.equals(localContentTagMd5); + String localContentGrayMd5 = ConfigCacheService.getContentGrayMd5(groupKey, grayName); + boolean md5Changed = !md5.equals(localContentGrayMd5); - if (md5Changed) { - ConfigDiskServiceFactory.getInstance().saveTagToDisk(dataId, group, tenant, tag, content); + GrayRule localGrayRule = ConfigCacheService.getGrayRule(groupKey, grayName); + GrayRule grayRuleNew = GrayRuleManager.constructGrayRule( + GrayRuleManager.deserializeConfigGrayPersistInfo(grayRule)); + if (grayRuleNew == null) { + DUMP_LOG.warn("[dump-gray-exception] . " + groupKey + ", unknown gray rule for gray name" + grayName); + return false; } + boolean grayRuleChanged = !grayRuleNew.equals(localGrayRule); + if (md5Changed) { - DUMP_LOG.warn( - "[dump-tag] md5 changed, update local jvm cache, groupKey={},tag={}, newMd5={},oldMd5={},lastModifiedTs={}", - groupKey, tag, md5, localContentTagMd5, lastModifiedTs); - updateTagMd5(groupKey, tag, md5, lastModifiedTs, encryptedDataKey4Tag); + DUMP_LOG.info( + "[dump-gray] md5 changed, update local jvm cache& local disk cache, groupKey={},grayName={}, " + + "newMd5={},oldMd5={}, newGrayRule={}, oldGrayRule={},lastModifiedTs={}", groupKey, + grayName, md5, localContentGrayMd5, grayRule, localGrayRule, lastModifiedTs); + updateGrayMd5(groupKey, grayName, grayRule, md5, lastModifiedTs, encryptedDataKey); + ConfigDiskServiceFactory.getInstance().saveGrayToDisk(dataId, group, tenant, grayName, content); + + } else if (grayRuleChanged) { + DUMP_LOG.info("[dump-gray] gray rule changed, update local jvm cache, groupKey={},grayName={}, " + + "newMd5={},oldMd5={}, newGrayRule={}, oldGrayRule={},lastModifiedTs={}", groupKey, grayName, + md5, localContentGrayMd5, grayRule, localGrayRule, lastModifiedTs); + updateGrayRule(groupKey, grayName, grayRule, lastModifiedTs, encryptedDataKey); } else if (timestampChanged) { - DUMP_LOG.warn( - "[dump-tag] timestamp changed, update last modified in local jvm cache, groupKey={},tag={}," - + "tagLastModifiedTs={},oldTagLastModifiedTs={}", groupKey, tag, lastModifiedTs, - localTagLastModifiedTs); - updateTagTimeStamp(groupKey, tag, lastModifiedTs); + DUMP_LOG.info( + "[dump-gray] timestamp changed, update last modified in local jvm cache, groupKey={},grayName={}," + + "grayLastModifiedTs={},oldgrayLastModifiedTs={}", groupKey, grayName, lastModifiedTs, + localGrayLastModifiedTs); + updateGrayTimeStamp(groupKey, grayName, lastModifiedTs); } else { - DUMP_LOG.warn("[dump-tag-ignore] md5 & timestamp not changed. groupKey={},tag={}", groupKey, tag); + DUMP_LOG.warn("[dump-gray-ignore] md5 & timestamp not changed. groupKey={},grayName={}", groupKey, + grayName); } return true; } catch (IOException ioe) { - DUMP_LOG.error("[dump-tag-exception] save disk error. " + groupKey + ", " + ioe.toString(), ioe); + DUMP_LOG.error("[dump-gray-exception] save disk error. " + groupKey + ", " + ioe.toString(), ioe); return false; } finally { releaseWriteLock(groupKey); @@ -319,14 +258,15 @@ public static boolean dumpTag(String dataId, String group, String tenant, String } /** - * Delete config file, and delete cache. + * Delete gray config file, and delete cache. * - * @param dataId dataId string value. - * @param group group string value. - * @param tenant tenant string value. + * @param dataId dataId string value. + * @param group group string value. + * @param tenant tenant string value. + * @param grayName grayName string value. * @return remove success or not. */ - public static boolean remove(String dataId, String group, String tenant) { + public static boolean removeGray(String dataId, String group, String tenant, String grayName) { final String groupKey = GroupKey2.getKey(dataId, group, tenant); final int lockResult = tryWriteLock(groupKey); @@ -343,51 +283,24 @@ public static boolean remove(String dataId, String group, String tenant) { } try { - DUMP_LOG.info("[dump] remove local disk cache,groupKey={} ", groupKey); - ConfigDiskServiceFactory.getInstance().removeConfigInfo(dataId, group, tenant); + DUMP_LOG.info("[remove-gray-ok] remove gray in local disk cache,grayName={},groupKey={} ", grayName, + groupKey); + ConfigDiskServiceFactory.getInstance().removeConfigInfo4Gray(dataId, group, tenant, grayName); - CACHE.remove(groupKey); - DUMP_LOG.info("[dump] remove local jvm cache,groupKey={} ", groupKey); + CacheItem ci = CACHE.get(groupKey); + if (ci.getConfigCacheGray() != null) { + ci.getConfigCacheGray().remove(grayName); + if (ci.getConfigCacheGray().isEmpty()) { + ci.clearConfigGrays(); + } else { + ci.sortConfigGray(); + } + } - NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); - - return true; - } finally { - releaseWriteLock(groupKey); - } - } - - /** - * Delete beta config file, and delete cache. - * - * @param dataId dataId string value. - * @param group group string value. - * @param tenant tenant string value. - * @return remove success or not. - */ - public static boolean removeBeta(String dataId, String group, String tenant) { - final String groupKey = GroupKey2.getKey(dataId, group, tenant); - final int lockResult = tryWriteLock(groupKey); - - // If data is non-existent. - if (0 == lockResult) { - DUMP_LOG.info("[remove-ok] {} not exist.", groupKey); - return true; - } - - // try to lock failed - if (lockResult < 0) { - DUMP_LOG.warn("[remove-error] write lock failed. {}", groupKey); - return false; - } - - try { - DUMP_LOG.info("[remove-beta-ok] remove beta in local disk cache,groupKey={} ", groupKey); - ConfigDiskServiceFactory.getInstance().removeConfigInfo4Beta(dataId, group, tenant); - NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, CACHE.get(groupKey).getIps4Beta())); - CACHE.get(groupKey).removeBeta(); - DUMP_LOG.info("[remove-beta-ok] remove beta in local jvm cache,groupKey={} ", groupKey); + DUMP_LOG.info("[remove-gray-ok] remove gray in local jvm cache,grayName={},groupKey={} ", grayName, + groupKey); + NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); return true; } finally { releaseWriteLock(groupKey); @@ -395,15 +308,14 @@ public static boolean removeBeta(String dataId, String group, String tenant) { } /** - * Delete tag config file, and delete cache. + * Delete config file, and delete cache. * * @param dataId dataId string value. * @param group group string value. * @param tenant tenant string value. - * @param tag tag string value. * @return remove success or not. */ - public static boolean removeTag(String dataId, String group, String tenant, String tag) { + public static boolean remove(String dataId, String group, String tenant) { final String groupKey = GroupKey2.getKey(dataId, group, tenant); final int lockResult = tryWriteLock(groupKey); @@ -420,20 +332,14 @@ public static boolean removeTag(String dataId, String group, String tenant, Stri } try { - DUMP_LOG.info("[remove-tag-ok] remove tag in local disk cache,tag={},groupKey={} ", tag, groupKey); - ConfigDiskServiceFactory.getInstance().removeConfigInfo4Tag(dataId, group, tenant, tag); + DUMP_LOG.info("[dump] remove local disk cache,groupKey={} ", groupKey); + ConfigDiskServiceFactory.getInstance().removeConfigInfo(dataId, group, tenant); - CacheItem ci = CACHE.get(groupKey); - if (ci.getConfigCacheTags() != null) { - ci.getConfigCacheTags().remove(tag); - if (ci.getConfigCacheTags().isEmpty()) { - ci.clearConfigTags(); - } - } + CACHE.remove(groupKey); + DUMP_LOG.info("[dump] remove local jvm cache,groupKey={} ", groupKey); - DUMP_LOG.info("[remove-tag-ok] remove tag in local jvm cache,tag={},groupKey={} ", tag, groupKey); + NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); - NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, tag)); return true; } finally { releaseWriteLock(groupKey); @@ -458,126 +364,112 @@ public static void updateMd5(String groupKey, String md5Utf8, long lastModifiedT } /** - * Update Beta md5 value. + * Update gray md5 value. * - * @param groupKey groupKey string value. - * @param md5Utf8 md5UTF8 string value. - * @param ips4Beta ips4Beta List. - * @param lastModifiedTs lastModifiedTs long value. + * @param groupKey groupKey string value. + * @param grayName grayName string value. + * @param grayRule grayRule string value. + * @param md5Utf8 md5UTF8 string value. + * @param lastModifiedTs lastModifiedTs long value. + * @param encryptedDataKey encryptedDataKey string value. */ - public static void updateBetaMd5(String groupKey, String md5Utf8, List ips4Beta, long lastModifiedTs, - String encryptedDataKey4Beta) { + private static void updateGrayMd5(String groupKey, String grayName, String grayRule, String md5Utf8, + long lastModifiedTs, String encryptedDataKey) { CacheItem cache = makeSure(groupKey, null); - cache.initBetaCacheIfEmpty(); - String betaMd5Utf8 = cache.getConfigCacheBeta().getMd5(ENCODE_UTF8); - if (betaMd5Utf8 == null || !betaMd5Utf8.equals(md5Utf8) || !CollectionUtils.isListEqual(ips4Beta, - cache.ips4Beta)) { - cache.isBeta = true; - cache.ips4Beta = ips4Beta; - cache.getConfigCacheBeta().setMd5Utf8(md5Utf8); - cache.getConfigCacheBeta().setLastModifiedTs(lastModifiedTs); - cache.getConfigCacheBeta().setEncryptedDataKey(encryptedDataKey4Beta); - NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta)); - } - } - - /** - * Update tag md5 value. - * - * @param groupKey groupKey string value. - * @param tag tag string value. - * @param md5Utf8 md5UTF8 string value. - * @param lastModifiedTs lastModifiedTs long value. - */ - public static void updateTagMd5(String groupKey, String tag, String md5Utf8, long lastModifiedTs, - String encryptedDataKey4Tag) { - CacheItem cache = makeSure(groupKey, null); - cache.initConfigTagsIfEmpty(tag); - ConfigCache configCache = cache.getConfigCacheTags().get(tag); + cache.initConfigGrayIfEmpty(grayName); + ConfigCacheGray configCache = cache.getConfigCacheGray().get(grayName); configCache.setMd5Utf8(md5Utf8); configCache.setLastModifiedTs(lastModifiedTs); - configCache.setEncryptedDataKey(encryptedDataKey4Tag); - NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, tag)); + configCache.setEncryptedDataKey(encryptedDataKey); + configCache.resetGrayRule(grayRule); + cache.sortConfigGray(); + NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); } /** * Get and return content md5 value from cache. Empty string represents no data. */ public static String getContentMd5(String groupKey) { - return getContentMd5(groupKey, "", ""); + return getContentMd5(groupKey, null, null); } public static String getContentMd5(String groupKey, String ip, String tag) { + return getContentMd5(groupKey, ip, tag, null, ENCODE_UTF8); + } + + public static String getContentMd5(String groupKey, String ip, String tag, Map connLabels, + String encode) { CacheItem item = CACHE.get(groupKey); - if (item != null && item.isBeta && item.ips4Beta != null && item.ips4Beta.contains(ip) - && item.getConfigCacheBeta() != null) { - return item.getConfigCacheBeta().getMd5(ENCODE_UTF8); + if (item == null) { + return NULL; } - - if (item != null && StringUtils.isNotBlank(tag) && item.getConfigCacheTags() != null - && item.getConfigCacheTags().containsKey(tag)) { - return item.getConfigCacheTags().get(tag).getMd5(ENCODE_UTF8); + if (connLabels == null && StringUtils.isNotBlank(ip)) { + connLabels = new HashMap<>(4); } - - if (item != null && item.isBatch && item.delimiter >= InternetAddressUtil.ipToInt(ip) - && item.getConfigCacheBatch() != null) { - return item.getConfigCacheBatch().getMd5(ENCODE_UTF8); + if (connLabels == null && StringUtils.isNotBlank(tag)) { + connLabels = new HashMap<>(4); } - return (null != item) ? item.getConfigCache().getMd5(ENCODE_UTF8) : Constants.NULL; + if (StringUtils.isNotBlank(ip)) { + connLabels.put(CLIENT_IP, ip); + } + if (StringUtils.isNotBlank(tag)) { + connLabels.put(VIPSERVER_TAG, tag); + } + if (item.getSortConfigGrays() != null && connLabels != null && !connLabels.isEmpty()) { + for (ConfigCacheGray entry : item.getSortConfigGrays()) { + if (entry.match(connLabels)) { + return entry.getMd5(encode); + } + } + } + String md5 = item.getConfigCache().getMd5(encode); + return md5 == null ? NULL : md5; } - /** - * Get and return beta md5 value from cache. Empty string represents no data. - */ - public static String getContentBetaMd5(String groupKey) { - CacheItem item = CACHE.get(groupKey); - - if (item == null || item.getConfigCacheBeta() == null) { - return Constants.NULL; - } - return item.getConfigCacheBeta().getMd5(ENCODE_UTF8); + private static void updateGrayRule(String groupKey, String grayName, String grayRule, long lastModifiedTs, + String encryptedDataKey) { + CacheItem cache = makeSure(groupKey, null); + cache.initConfigGrayIfEmpty(grayName); + ConfigCacheGray configCache = cache.getConfigCacheGray().get(grayName); + configCache.setLastModifiedTs(lastModifiedTs); + configCache.setEncryptedDataKey(encryptedDataKey); + configCache.resetGrayRule(grayRule); + cache.sortConfigGray(); + NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); } /** - * Get and return tag md5 value from cache. Empty string represents no data. + * Get and return gray md5 value from cache. Empty string represents no data. * * @param groupKey groupKey string value. - * @param tag tag string value. + * @param grayName grayName string value. * @return Content Tag Md5 value. */ - public static String getContentTagMd5(String groupKey, String tag) { + public static String getContentGrayMd5(String groupKey, String grayName) { CacheItem item = CACHE.get(groupKey); - if (item == null || item.getConfigCacheTags() == null || !item.getConfigCacheTags().containsKey(tag)) { - return Constants.NULL; + if (item == null || item.getConfigCacheGray() == null || !item.getConfigCacheGray().containsKey(grayName)) { + return NULL; } - return item.getConfigCacheTags().get(tag).getMd5(ENCODE_UTF8); + return item.getConfigCacheGray().get(grayName).getMd5(ENCODE_UTF8); } - /** - * Get and return beta ip list. - * - * @param groupKey groupKey string value. - * @return list beta ips. - */ - public static List getBetaIps(String groupKey) { + public static long getGrayLastModifiedTs(String groupKey, String grayName) { CacheItem item = CACHE.get(groupKey); - return (null != item) ? item.getIps4Beta() : Collections.emptyList(); - } - - public static long getBetaLastModifiedTs(String groupKey) { - CacheItem item = CACHE.get(groupKey); - return (null != item && item.getConfigCacheBeta() != null) ? item.getConfigCacheBeta().getLastModifiedTs() : 0L; + if (item.getConfigCacheGray() == null || !item.getConfigCacheGray().containsKey(grayName)) { + return 0; + } + ConfigCache configCacheGray = item.getConfigCacheGray().get(grayName); + + return (null != configCacheGray) ? configCacheGray.getLastModifiedTs() : 0; } - public static long getTagLastModifiedTs(String groupKey, String tag) { + public static GrayRule getGrayRule(String groupKey, String grayName) { CacheItem item = CACHE.get(groupKey); - if (item.getConfigCacheTags() == null || !item.getConfigCacheTags().containsKey(tag)) { - return 0; + if (item == null || item.getConfigCacheGray() == null || !item.getConfigCacheGray().containsKey(grayName)) { + return null; } - ConfigCache configCacheTag = item.getConfigCacheTags().get(tag); - - return (null != configCacheTag) ? configCacheTag.getLastModifiedTs() : 0; + return item.getConfigCacheGray().get(grayName).getGrayRule(); } /** @@ -596,26 +488,29 @@ public static long getLastModifiedTs(String groupKey) { } /** - * update tag timestamp. + * update gray timestamp. * * @param groupKey groupKey. - * @param tag tag. + * @param grayName grayName. * @param lastModifiedTs lastModifiedTs. */ - public static void updateTagTimeStamp(String groupKey, String tag, long lastModifiedTs) { + private static void updateGrayTimeStamp(String groupKey, String grayName, long lastModifiedTs) { CacheItem cache = makeSure(groupKey, null); - cache.initConfigTagsIfEmpty(tag); - cache.getConfigCacheTags().get(tag).setLastModifiedTs(lastModifiedTs); - + cache.initConfigGrayIfEmpty(grayName); + cache.getConfigCacheGray().get(grayName).setLastModifiedTs(lastModifiedTs); } public static boolean isUptodate(String groupKey, String md5) { - String serverMd5 = ConfigCacheService.getContentMd5(groupKey); - return StringUtils.equals(md5, serverMd5); + return isUptodate(groupKey, md5, null, null); } public static boolean isUptodate(String groupKey, String md5, String ip, String tag) { - String serverMd5 = ConfigCacheService.getContentMd5(groupKey, ip, tag); + return isUptodate(groupKey, md5, ip, tag, null); + } + + public static boolean isUptodate(String groupKey, String md5, String ip, String tag, + Map appLabels) { + String serverMd5 = ConfigCacheService.getContentMd5(groupKey, ip, tag, appLabels, ENCODE_UTF8); return StringUtils.equals(md5, serverMd5); } @@ -687,41 +582,11 @@ static CacheItem makeSure(final String groupKey, final String encryptedDataKey) * @param lastModifiedTs lastModifiedTs. * @param encryptedDataKey encryptedDataKey. */ - public static void updateTimeStamp(String groupKey, long lastModifiedTs, String encryptedDataKey) { + private static void updateTimeStamp(String groupKey, long lastModifiedTs, String encryptedDataKey) { CacheItem cache = makeSure(groupKey, encryptedDataKey); cache.getConfigCache().setLastModifiedTs(lastModifiedTs); } - /** - * update beta ip list. - * - * @param groupKey groupKey. - * @param ips4Beta ips4Beta. - * @param lastModifiedTs lastModifiedTs. - */ - private static void updateBetaIpList(String groupKey, List ips4Beta, long lastModifiedTs) { - CacheItem cache = makeSure(groupKey, null); - cache.initBetaCacheIfEmpty(); - cache.setBeta(true); - cache.setIps4Beta(ips4Beta); - cache.getConfigCacheBeta().setLastModifiedTs(lastModifiedTs); - NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey, true, ips4Beta)); - - } - - /** - * update beta lastModifiedTs. - * - * @param groupKey groupKey. - * @param lastModifiedTs lastModifiedTs. - */ - private static void updateBetaTimeStamp(String groupKey, long lastModifiedTs) { - CacheItem cache = makeSure(groupKey, null); - cache.initBetaCacheIfEmpty(); - cache.getConfigCacheBeta().setLastModifiedTs(lastModifiedTs); - - } - private static final int TRY_GET_LOCK_TIMES = 9; /** diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigGrayModelMigrateService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigGrayModelMigrateService.java new file mode 100644 index 00000000000..e2115141c46 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigGrayModelMigrateService.java @@ -0,0 +1,191 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service; + +import com.alibaba.nacos.api.utils.NetUtils; +import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; +import com.alibaba.nacos.persistence.model.Page; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; + +import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG; + +/** + * migrate beta and tag to gray model. should only invoked from config sync notify. + * + * @author shiyiyue + */ +@Service +public class ConfigGrayModelMigrateService { + + ConfigInfoBetaPersistService configInfoBetaPersistService; + + ConfigInfoTagPersistService configInfoTagPersistService; + + ConfigInfoGrayPersistService configInfoGrayPersistService; + + public ConfigGrayModelMigrateService(ConfigInfoBetaPersistService configInfoBetaPersistService, + ConfigInfoTagPersistService configInfoTagPersistService, + ConfigInfoGrayPersistService configInfoGrayPersistService) { + this.configInfoBetaPersistService = configInfoBetaPersistService; + this.configInfoGrayPersistService = configInfoGrayPersistService; + this.configInfoTagPersistService = configInfoTagPersistService; + } + + /** + * migrate beta&tag to gray . + */ + @PostConstruct + public void migrate() { + doCheckMigrate(); + } + + /** + * migrate single config beta. + * + * @param dataId dataId. + * @param group group. + * @param tenant tenant. + */ + public void checkMigrateBeta(String dataId, String group, String tenant) { + ConfigInfoBetaWrapper configInfo4Beta = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant); + if (configInfo4Beta == null) { + ConfigInfoGrayWrapper configInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, + tenant, BetaGrayRule.TYPE_BETA); + if (configInfoGrayWrapper == null) { + return; + } + configInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, BetaGrayRule.TYPE_BETA, + NetUtils.localIP(), "nacos_auto_migrate"); + return; + } + ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant, + BetaGrayRule.TYPE_BETA); + if (configInfo4Gray == null || configInfo4Gray.getLastModified() < configInfo4Beta.getLastModified()) { + DEFAULT_LOG.info("[migrate beta to gray] dataId={}, group={}, tenant={}, md5={}", + configInfo4Beta.getDataId(), configInfo4Beta.getGroup(), configInfo4Beta.getTenant(), + configInfo4Beta.getMd5()); + ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA, + BetaGrayRule.VERSION, configInfo4Beta.getBetaIps(), BetaGrayRule.PRIORITY); + configInfoGrayPersistService.insertOrUpdateGray(configInfo4Beta, BetaGrayRule.TYPE_BETA, + GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), NetUtils.localIP(), + "nacos_auto_migrate"); + } + + } + + /** + * migrate single config tag. + * + * @param dataId dataId. + * @param group group. + * @param tenant tenant. + * @param tag tag. + */ + public void checkMigrateTag(String dataId, String group, String tenant, String tag) { + ConfigInfoTagWrapper configInfo4Tag = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, + tag); + if (configInfo4Tag == null) { + ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, + tenant, TagGrayRule.TYPE_TAG + "_" + tag); + if (configInfo4Gray == null) { + return; + } + configInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, TagGrayRule.TYPE_TAG + "_" + tag, + NetUtils.localIP(), "nacos_auto_migrate"); + return; + } + ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant, + TagGrayRule.TYPE_TAG + "_" + tag); + if (configInfo4Gray == null || configInfo4Gray.getLastModified() < configInfo4Tag.getLastModified()) { + DEFAULT_LOG.info("[migrate tag to gray] dataId={}, group={}, tenant={}, md5={}", + configInfo4Tag.getDataId(), configInfo4Tag.getGroup(), configInfo4Tag.getTenant(), + configInfo4Tag.getMd5()); + ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, + TagGrayRule.VERSION, configInfo4Tag.getTag(), TagGrayRule.PRIORITY); + configInfoGrayPersistService.insertOrUpdateGray(configInfo4Tag, TagGrayRule.TYPE_TAG, + GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), NetUtils.localIP(), + "nacos_auto_migrate"); + } + } + + private void doCheckMigrate() { + int pageSize = 100; + int rowCount = configInfoBetaPersistService.configInfoBetaCount(); + int pageCount = (int) Math.ceil(rowCount * 1.0 / pageSize); + int actualRowCount = 0; + for (int pageNo = 1; pageNo <= pageCount; pageNo++) { + Page page = configInfoBetaPersistService.findAllConfigInfoBetaForDumpAll(pageNo, + pageSize); + if (page != null) { + for (ConfigInfoBetaWrapper cf : page.getPageItems()) { + + ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray( + cf.getDataId(), cf.getGroup(), cf.getTenant(), BetaGrayRule.TYPE_BETA); + if (configInfo4Gray == null || configInfo4Gray.getLastModified() < cf.getLastModified()) { + DEFAULT_LOG.info("[migrate beta to gray] dataId={}, group={}, tenant={}, md5={}", + cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getMd5()); + ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo( + BetaGrayRule.TYPE_BETA, BetaGrayRule.VERSION, cf.getBetaIps(), BetaGrayRule.PRIORITY); + configInfoGrayPersistService.insertOrUpdateGray(cf, BetaGrayRule.TYPE_BETA, + GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), + NetUtils.localIP(), "nacos_auto_migrate"); + } + + } + actualRowCount += page.getPageItems().size(); + } + } + + rowCount = configInfoTagPersistService.configInfoTagCount(); + pageCount = (int) Math.ceil(rowCount * 1.0 / pageSize); + actualRowCount = 0; + for (int pageNo = 1; pageNo <= pageCount; pageNo++) { + Page page = configInfoTagPersistService.findAllConfigInfoTagForDumpAll(pageNo, + pageSize); + if (page != null) { + for (ConfigInfoTagWrapper cf : page.getPageItems()) { + ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray( + cf.getDataId(), cf.getGroup(), cf.getTenant(), TagGrayRule.TYPE_TAG + "_" + cf.getTag()); + if (configInfo4Gray == null || configInfo4Gray.getLastModified() < cf.getLastModified()) { + DEFAULT_LOG.info("[migrate tag to gray] dataId={}, group={}, tenant={}, md5={}", + cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getMd5()); + ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo( + TagGrayRule.TYPE_TAG, TagGrayRule.VERSION, cf.getTag(), TagGrayRule.PRIORITY); + configInfoGrayPersistService.insertOrUpdateGray(cf, TagGrayRule.TYPE_TAG + "_" + cf.getTag(), + GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), + NetUtils.localIP(), "nacos_auto_migrate"); + } + } + + actualRowCount += page.getPageItems().size(); + DEFAULT_LOG.info("[-tag] {} / {}", actualRowCount, rowCount); + } + } + } + +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigOperationService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigOperationService.java index b6f5a72d08b..146a4646473 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigOperationService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigOperationService.java @@ -20,6 +20,7 @@ import com.alibaba.nacos.api.exception.api.NacosApiException; import com.alibaba.nacos.api.model.v2.ErrorCode; import com.alibaba.nacos.common.utils.MapUtil; +import com.alibaba.nacos.common.utils.NumberUtils; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.ConfigOperateResult; @@ -27,13 +28,21 @@ import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; import com.alibaba.nacos.config.server.model.event.IstioConfigChangeEvent; import com.alibaba.nacos.config.server.model.form.ConfigForm; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo; +import com.alibaba.nacos.config.server.model.gray.GrayRule; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import com.alibaba.nacos.config.server.utils.ConfigTagUtil; import com.alibaba.nacos.config.server.utils.ParamUtils; +import com.alibaba.nacos.config.server.utils.PropertyUtil; import com.alibaba.nacos.config.server.utils.TimeUtils; +import com.alibaba.nacos.sys.env.EnvUtil; import com.alibaba.nacos.sys.utils.InetUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,6 +51,7 @@ import java.sql.Timestamp; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -60,14 +70,18 @@ public class ConfigOperationService { private ConfigInfoBetaPersistService configInfoBetaPersistService; + private ConfigInfoGrayPersistService configInfoGrayPersistService; + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigOperationService.class); public ConfigOperationService(ConfigInfoPersistService configInfoPersistService, ConfigInfoTagPersistService configInfoTagPersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService) { + ConfigInfoBetaPersistService configInfoBetaPersistService, + ConfigInfoGrayPersistService configInfoGrayPersistService) { this.configInfoPersistService = configInfoPersistService; this.configInfoTagPersistService = configInfoTagPersistService; this.configInfoBetaPersistService = configInfoBetaPersistService; + this.configInfoGrayPersistService = configInfoGrayPersistService; } /** @@ -81,13 +95,7 @@ public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequ Map configAdvanceInfo = getConfigAdvanceInfo(configForm); ParamUtils.checkParam(configAdvanceInfo); - if (AggrWhitelist.isAggrDataId(configForm.getDataId())) { - LOGGER.warn("[aggr-conflict] {} attempt to publish single data, {}, {}", configRequestInfo.getSrcIp(), - configForm.getDataId(), configForm.getGroup()); - throw new NacosApiException(HttpStatus.FORBIDDEN.value(), ErrorCode.INVALID_DATA_ID, - "dataId:" + configForm.getDataId() + " is aggr"); - } - + configForm.setEncryptedDataKey(encryptedDataKey); ConfigInfo configInfo = new ConfigInfo(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(), configForm.getAppName(), configForm.getContent()); //set old md5 @@ -98,103 +106,229 @@ public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequ configInfo.setEncryptedDataKey(encryptedDataKey); ConfigOperateResult configOperateResult; - String persistEvent = ConfigTraceService.PERSISTENCE_EVENT; + //beta publish + if (StringUtils.isNotBlank(configRequestInfo.getBetaIps())) { + configForm.setGrayName(BetaGrayRule.TYPE_BETA); + configForm.setGrayRuleExp(configRequestInfo.getBetaIps()); + configForm.setGrayVersion(BetaGrayRule.VERSION); + persistBeta(configForm, configInfo, configRequestInfo); + configForm.setGrayPriority(Integer.MAX_VALUE); + publishConfigGray(BetaGrayRule.TYPE_BETA, configForm, configRequestInfo); + return Boolean.TRUE; + } + // tag publish + if (StringUtils.isNotBlank(configForm.getTag())) { + configForm.setGrayName(TagGrayRule.TYPE_TAG + "_" + configForm.getTag()); + configForm.setGrayRuleExp(configForm.getTag()); + configForm.setGrayVersion(TagGrayRule.VERSION); + configForm.setGrayPriority(Integer.MAX_VALUE - 1); + persistTagv1(configForm, configInfo, configRequestInfo); + publishConfigGray(TagGrayRule.TYPE_TAG, configForm, configRequestInfo); + return Boolean.TRUE; + } - if (StringUtils.isBlank(configRequestInfo.getBetaIps())) { - if (StringUtils.isBlank(configForm.getTag())) { - if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { - configOperateResult = configInfoPersistService.insertOrUpdateCas(configRequestInfo.getSrcIp(), - configForm.getSrcUser(), configInfo, configAdvanceInfo); - if (!configOperateResult.isSuccess()) { - LOGGER.warn( - "[cas-publish-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.", - configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5()); - throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), - ErrorCode.RESOURCE_CONFLICT, "Cas publish fail, server md5 may have changed."); - } - } else { - configOperateResult = configInfoPersistService.insertOrUpdate(configRequestInfo.getSrcIp(), - configForm.getSrcUser(), configInfo, configAdvanceInfo); - } - ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configForm.getDataId(), configForm.getGroup(), - configForm.getNamespaceId(), configOperateResult.getLastModified())); - if (ConfigTagUtil.isIstio(configForm.getConfigTags())) { - ConfigChangePublisher.notifyConfigChange( - new IstioConfigChangeEvent(configForm.getDataId(), configForm.getGroup(), - configOperateResult.getLastModified(), configForm.getContent(), - ConfigTagUtil.getIstioType(configForm.getConfigTags()))); - } - } else { - if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { - configOperateResult = configInfoTagPersistService.insertOrUpdateTagCas(configInfo, - configForm.getTag(), configRequestInfo.getSrcIp(), configForm.getSrcUser()); - if (!configOperateResult.isSuccess()) { - LOGGER.warn( - "[cas-publish-tag-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.", - configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5()); - throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), - ErrorCode.RESOURCE_CONFLICT, - "Cas publish tag config fail, server md5 may have changed."); - } - } else { - configOperateResult = configInfoTagPersistService.insertOrUpdateTag(configInfo, configForm.getTag(), - configRequestInfo.getSrcIp(), configForm.getSrcUser()); - } - persistEvent = ConfigTraceService.PERSISTENCE_EVENT_TAG + "-" + configForm.getTag(); - ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configForm.getDataId(), configForm.getGroup(), - configForm.getNamespaceId(), configForm.getTag(), - configOperateResult.getLastModified())); + //formal publish + if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { + configOperateResult = configInfoPersistService.insertOrUpdateCas(configRequestInfo.getSrcIp(), + configForm.getSrcUser(), configInfo, configAdvanceInfo); + if (!configOperateResult.isSuccess()) { + LOGGER.warn( + "[cas-publish-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.", + configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5()); + throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT, + "Cas publish fail, server md5 may have changed."); } } else { - // beta publish - if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { - configOperateResult = configInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, - configRequestInfo.getBetaIps(), configRequestInfo.getSrcIp(), configForm.getSrcUser()); - if (!configOperateResult.isSuccess()) { - LOGGER.warn( - "[cas-publish-beta-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.", - configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5()); - throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT, - "Cas publish beta config fail, server md5 may have changed."); - } - } else { - configOperateResult = configInfoBetaPersistService.insertOrUpdateBeta(configInfo, - configRequestInfo.getBetaIps(), configRequestInfo.getSrcIp(), configForm.getSrcUser()); - } - persistEvent = ConfigTraceService.PERSISTENCE_EVENT_BETA; + configOperateResult = configInfoPersistService.insertOrUpdate(configRequestInfo.getSrcIp(), + configForm.getSrcUser(), configInfo, configAdvanceInfo); + } + ConfigChangePublisher.notifyConfigChange( + new ConfigDataChangeEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(), + configOperateResult.getLastModified())); + if (ConfigTagUtil.isIstio(configForm.getConfigTags())) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(true, configForm.getDataId(), configForm.getGroup(), - configForm.getNamespaceId(), configOperateResult.getLastModified())); + new IstioConfigChangeEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(), + configOperateResult.getLastModified(), configForm.getContent(), + ConfigTagUtil.getIstioType(configForm.getConfigTags()))); } ConfigTraceService.logPersistenceEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(), configRequestInfo.getRequestIpApp(), configOperateResult.getLastModified(), - InetUtils.getSelfIP(), persistEvent, ConfigTraceService.PERSISTENCE_TYPE_PUB, configForm.getContent()); + InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB, + configForm.getContent()); + return true; } + private void persistTagv1(ConfigForm configForm, ConfigInfo configInfo, ConfigRequestInfo configRequestInfo) + throws NacosApiException { + if (!PropertyUtil.isGrayCompatibleModel()) { + return; + } + + ConfigOperateResult configOperateResult = null; + if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { + configOperateResult = configInfoTagPersistService.insertOrUpdateTagCas(configInfo, configForm.getTag(), + configRequestInfo.getSrcIp(), configForm.getSrcUser()); + if (!configOperateResult.isSuccess()) { + LOGGER.warn( + "[cas-publish-tag-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.", + configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5()); + throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT, + "Cas publish tag config fail, server md5 may have changed."); + } + } else { + configOperateResult = configInfoTagPersistService.insertOrUpdateTag(configInfo, configForm.getTag(), + configRequestInfo.getSrcIp(), configForm.getSrcUser()); + } + } + + private void persistBeta(ConfigForm configForm, ConfigInfo configInfo, ConfigRequestInfo configRequestInfo) + throws NacosApiException { + if (!PropertyUtil.isGrayCompatibleModel()) { + return; + } + ConfigOperateResult configOperateResult = null; + // beta publish + if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { + configOperateResult = configInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, + configRequestInfo.getBetaIps(), configRequestInfo.getSrcIp(), configForm.getSrcUser()); + if (!configOperateResult.isSuccess()) { + LOGGER.warn( + "[cas-publish-beta-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.", + configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5()); + throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT, + "Cas publish beta config fail, server md5 may have changed."); + } + } else { + configInfoBetaPersistService.insertOrUpdateBeta(configInfo, + configRequestInfo.getBetaIps(), configRequestInfo.getSrcIp(), configForm.getSrcUser()); + } + + } + + /** + * publish gray config tag v2. + * + * @param configForm ConfigForm + * @param configRequestInfo ConfigRequestInfo + * @return boolean + * @throws NacosException NacosException. + * @date 2024/2/5 + */ + private Boolean publishConfigGray(String grayType, ConfigForm configForm, ConfigRequestInfo configRequestInfo) + throws NacosException { + + Map configAdvanceInfo = getConfigAdvanceInfo(configForm); + ParamUtils.checkParam(configAdvanceInfo); + + ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(grayType, + configForm.getGrayVersion(), configForm.getGrayRuleExp(), configForm.getGrayPriority()); + GrayRule grayRuleStruct = GrayRuleManager.constructGrayRule(localConfigGrayPersistInfo); + if (grayRuleStruct == null) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_VERSION_INVALID, + ErrorCode.CONFIG_GRAY_VERSION_INVALID.getMsg()); + } + + if (!grayRuleStruct.isValid()) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_RULE_FORMAT_INVALID, + ErrorCode.CONFIG_GRAY_RULE_FORMAT_INVALID.getMsg()); + } + + //version count check. + if (checkGrayVersionOverMaxCount(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(), + configForm.getGrayName())) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_OVER_MAX_VERSION_COUNT, + "gray config version is over max count :" + getMaxGrayVersionCount()); + } + + ConfigInfo configInfo = new ConfigInfo(configForm.getDataId(), configForm.getGroup(), + configForm.getNamespaceId(), configForm.getAppName(), configForm.getContent()); + configInfo.setType(configForm.getType()); + configInfo.setEncryptedDataKey(configForm.getEncryptedDataKey()); + + ConfigOperateResult configOperateResult; + + if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) { + configOperateResult = configInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, + configForm.getGrayName(), + GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), + configRequestInfo.getSrcIp(), configForm.getSrcUser()); + if (!configOperateResult.isSuccess()) { + LOGGER.warn( + "[cas-publish-gray-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, grayName = {}, msg = server md5 may have changed.", + configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5(), + configForm.getGrayName()); + throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT, + "Cas publish gray config fail, server md5 may have changed."); + } + } else { + configOperateResult = configInfoGrayPersistService.insertOrUpdateGray(configInfo, configForm.getGrayName(), + GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), + configRequestInfo.getSrcIp(), configForm.getSrcUser()); + } + + ConfigChangePublisher.notifyConfigChange( + new ConfigDataChangeEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(), + configForm.getGrayName(), configOperateResult.getLastModified())); + + String eventType = ConfigTraceService.PERSISTENCE_EVENT + "-" + configForm.getGrayName(); + + ConfigTraceService.logPersistenceEvent(configForm.getDataId(), configForm.getGroup(), + configForm.getNamespaceId(), configRequestInfo.getRequestIpApp(), configOperateResult.getLastModified(), + InetUtils.getSelfIP(), eventType, ConfigTraceService.PERSISTENCE_TYPE_PUB, configForm.getContent()); + return true; + } + + private boolean checkGrayVersionOverMaxCount(String dataId, String group, String tenant, String grayName) { + List configInfoGrays = configInfoGrayPersistService.findConfigInfoGrays(dataId, group, tenant); + if (configInfoGrays == null || configInfoGrays.isEmpty()) { + return false; + } else { + if (configInfoGrays.contains(grayName)) { + return false; + } + return configInfoGrays.size() >= getMaxGrayVersionCount(); + } + } + + private static final int DEFAULT_MAX_GRAY_VERSION_COUNT = 10; + + private int getMaxGrayVersionCount() { + String value = EnvUtil.getProperty("nacos.config.gray.version.max.count", ""); + return NumberUtils.isDigits(value) ? NumberUtils.toInt(value) : DEFAULT_MAX_GRAY_VERSION_COUNT; + } + /** * Synchronously delete all pre-aggregation data under a dataId. */ public Boolean deleteConfig(String dataId, String group, String namespaceId, String tag, String clientIp, String srcUser) { String persistEvent = ConfigTraceService.PERSISTENCE_EVENT; + String grayName = ""; if (StringUtils.isBlank(tag)) { configInfoPersistService.removeConfigInfo(dataId, group, namespaceId, clientIp, srcUser); } else { persistEvent = ConfigTraceService.PERSISTENCE_EVENT_TAG + "-" + tag; - configInfoTagPersistService.removeConfigInfoTag(dataId, group, namespaceId, tag, clientIp, srcUser); + grayName = TagGrayRule.TYPE_TAG + "_" + tag; + configInfoGrayPersistService.removeConfigInfoGray(dataId, group, namespaceId, grayName, clientIp, srcUser); + deleteConfigTagv1(dataId, group, namespaceId, tag, clientIp, srcUser); } final Timestamp time = TimeUtils.getCurrentTime(); ConfigTraceService.logPersistenceEvent(dataId, group, namespaceId, null, time.getTime(), clientIp, persistEvent, ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null); ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, dataId, group, namespaceId, tag, time.getTime())); + new ConfigDataChangeEvent(dataId, group, namespaceId, grayName, time.getTime())); return true; } + private void deleteConfigTagv1(String dataId, String group, String namespaceId, String tag, String clientIp, + String srcUser) { + if (PropertyUtil.isGrayCompatibleModel()) { + configInfoTagPersistService.removeConfigInfoTag(dataId, group, namespaceId, tag, clientIp, srcUser); + } + } + public Map getConfigAdvanceInfo(ConfigForm configForm) { Map configAdvanceInfo = new HashMap<>(10); MapUtil.putIfValNoNull(configAdvanceInfo, "config_tags", configForm.getConfigTags()); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigSubService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigSubService.java index ebf7afabb1a..1a2d3f42bce 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigSubService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigSubService.java @@ -160,12 +160,13 @@ public T call() throws Exception { List runJobs() { Collection ipList = serverMemberManager.allMembers(); List collectionResult = new ArrayList<>(ipList.size()); + // Submit query task. for (Member ip : ipList) { try { completionService.submit(new Job(ip.getAddress()) { }); - } catch (Exception e) { // Send request failed. + } catch (Throwable e) { // Send request failed. LogUtil.DEFAULT_LOG.warn("invoke to {} with exception: {} during submit job", ip, e.getMessage()); } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingService.java index d79b34cd421..ab571ca02ff 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingService.java @@ -21,7 +21,6 @@ import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.notify.listener.Subscriber; import com.alibaba.nacos.common.utils.ExceptionUtil; -import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.model.SampleResult; import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent; import com.alibaba.nacos.config.server.monitor.MetricsMonitor; @@ -243,7 +242,7 @@ public LongPollingService() { public void onEvent(Event event) { if (event instanceof LocalDataChangeEvent) { LocalDataChangeEvent evt = (LocalDataChangeEvent) event; - ConfigExecutor.executeLongPolling(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps)); + ConfigExecutor.executeLongPolling(new DataChangeTask(evt.groupKey)); } } @@ -274,11 +273,6 @@ public void run() { ClientLongPolling clientSub = iter.next(); if (clientSub.clientMd5Map.containsKey(groupKey)) { - // If published tag is not in the tag list, then it skipped. - if (StringUtils.isNotBlank(tag) && !tag.equals(clientSub.tag)) { - continue; - } - getRetainIps().put(clientSub.ip, System.currentTimeMillis()); iter.remove(); // Delete subscribers' relationships. LogUtil.CLIENT_LOG.info("{}|{}|{}|{}|{}|{}|{}", (System.currentTimeMillis() - changeTime), @@ -294,26 +288,14 @@ public void run() { } } - DataChangeTask(String groupKey, boolean isBeta, List betaIps) { - this(groupKey, isBeta, betaIps, null); - } - - DataChangeTask(String groupKey, boolean isBeta, List betaIps, String tag) { + DataChangeTask(String groupKey) { this.groupKey = groupKey; - this.isBeta = isBeta; - this.betaIps = betaIps; - this.tag = tag; } final String groupKey; final long changeTime = System.currentTimeMillis(); - final boolean isBeta; - - final List betaIps; - - final String tag; } class StatTask implements Runnable { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorker.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorker.java index 90bec3e9884..d3a05b740da 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorker.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorker.java @@ -82,14 +82,14 @@ public void run() { while (true) { List configDeleted = historyConfigInfoPersistService.findDeletedConfig(startTime, - deleteCursorId, pageSize); + deleteCursorId, pageSize, Constants.FORMAL); for (ConfigInfoStateWrapper configInfo : configDeleted) { if (configInfoPersistService.findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()) == null) { ConfigCacheService.remove(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); - LogUtil.DEFAULT_LOG.info("[dump-delete-ok] {}", - new Object[] {GroupKey2.getKey(configInfo.getDataId(), configInfo.getGroup())}); + LogUtil.DEFAULT_LOG.info("[dump-delete-ok], groupKey: {}, tenant: {}", + new Object[] {GroupKey2.getKey(configInfo.getDataId(), configInfo.getGroup())}, configInfo.getTenant()); } } if (configDeleted.size() < pageSize) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorker.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorker.java new file mode 100644 index 00000000000..5aa3b76c600 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorker.java @@ -0,0 +1,149 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.dump; + +import com.alibaba.nacos.common.utils.MD5Utils; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.config.server.constant.Constants; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; +import com.alibaba.nacos.config.server.service.ConfigCacheService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; +import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.utils.ConfigExecutor; +import com.alibaba.nacos.config.server.utils.GroupKey2; +import com.alibaba.nacos.config.server.utils.LogUtil; +import com.alibaba.nacos.config.server.utils.PropertyUtil; + +import java.sql.Timestamp; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * Dump gray config worker. + * + * @author shiyiyue + */ +public class DumpChangeGrayConfigWorker implements Runnable { + + Timestamp startTime; + + ConfigInfoGrayPersistService configInfoGrayPersistService; + + private final HistoryConfigInfoPersistService historyConfigInfoPersistService; + + int pageSize = 100; + + public DumpChangeGrayConfigWorker(ConfigInfoGrayPersistService configInfoGrayPersistService, Timestamp startTime, + HistoryConfigInfoPersistService historyConfigInfoPersistService) { + this.configInfoGrayPersistService = configInfoGrayPersistService; + this.startTime = startTime; + this.historyConfigInfoPersistService = historyConfigInfoPersistService; + } + + @Override + public void run() { + try { + if (!PropertyUtil.isDumpChangeOn()) { + LogUtil.DEFAULT_LOG.info("DumpGrayChange task is not open"); + return; + } + Timestamp currentTime = new Timestamp(System.currentTimeMillis()); + LogUtil.DEFAULT_LOG.info("DumpGrayChange start ,from time {},current time {}", startTime, currentTime); + + LogUtil.DEFAULT_LOG.info("Start to check delete configs from time {}", startTime); + long startDeletedConfigTime = System.currentTimeMillis(); + long deleteCursorId = 0L; + while (true) { + List configDeleted = historyConfigInfoPersistService.findDeletedConfig(startTime, + deleteCursorId, pageSize, Constants.GRAY); + for (ConfigInfoStateWrapper configInfo : configDeleted) { + String grayName = configInfo.getGrayName(); + if (StringUtils.isBlank(grayName)) { + continue; + } + + ConfigInfoStateWrapper configInfoStateWrapper = configInfoGrayPersistService.findConfigInfo4GrayState(configInfo.getDataId(), + configInfo.getGroup(), configInfo.getTenant(), grayName); + if (configInfoStateWrapper == null) { + ConfigCacheService.removeGray(configInfo.getDataId(), configInfo.getGroup(), + configInfo.getTenant(), grayName); + LogUtil.DEFAULT_LOG.info("[dump-gray-delete-ok], groupKey: {}, tenant: {}, grayName: {}", + GroupKey2.getKey(configInfo.getDataId(), configInfo.getGroup()), configInfo.getTenant(), grayName); + } + } + if (configDeleted.size() < pageSize) { + break; + } + deleteCursorId = configDeleted.get(configDeleted.size() - 1).getId(); + } + LogUtil.DEFAULT_LOG.info("Check delete configs finished,cost:{}", + System.currentTimeMillis() - startDeletedConfigTime); + + LogUtil.DEFAULT_LOG.info("Check changeGrayConfig start"); + long startChangeConfigTime = System.currentTimeMillis(); + + long changeCursorId = 0L; + while (true) { + LogUtil.DEFAULT_LOG.info("Check changed gray configs from time {},lastMaxId={}", startTime, + changeCursorId); + List changeConfigs = configInfoGrayPersistService.findChangeConfig(startTime, + changeCursorId, pageSize); + for (ConfigInfoGrayWrapper cf : changeConfigs) { + final String groupKey = GroupKey2.getKey(cf.getDataId(), cf.getGroup(), cf.getTenant()); + //check md5 & localtimestamp update local disk cache. + boolean newLastModified = cf.getLastModified() > ConfigCacheService.getLastModifiedTs(groupKey); + String localContentMd5 = ConfigCacheService.getContentMd5(groupKey); + boolean md5Update = !localContentMd5.equals(cf.getMd5()); + if (newLastModified || md5Update) { + LogUtil.DEFAULT_LOG.info("[dump-change-gray] find change config {}, {}, md5={}", + new Object[] {groupKey, cf.getLastModified(), cf.getMd5()}); + + LogUtil.DUMP_LOG.info("[dump-change-gray] find change config {}, {}, md5={}", + new Object[] {groupKey, cf.getLastModified(), cf.getMd5()}); + ConfigCacheService.dumpGray(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getGrayName(), + cf.getGrayRule(), cf.getContent(), cf.getLastModified(), cf.getEncryptedDataKey()); + final String content = cf.getContent(); + final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE_GBK); + final String md5Utf8 = MD5Utils.md5Hex(content, Constants.ENCODE_UTF8); + + LogUtil.DEFAULT_LOG.info("[dump-change-gray-ok] {}, {}, length={}, md5={},md5UTF8={}", + new Object[] {groupKey, cf.getLastModified(), content.length(), md5, md5Utf8}); + } + } + if (changeConfigs.size() < pageSize) { + break; + } + changeCursorId = changeConfigs.get(changeConfigs.size() - 1).getId(); + } + + long endChangeConfigTime = System.currentTimeMillis(); + LogUtil.DEFAULT_LOG.info( + "Check changed gray configs finished,cost:{}, next task running will from start time {}", + endChangeConfigTime - startChangeConfigTime, currentTime); + startTime = currentTime; + } catch (Throwable e) { + LogUtil.DEFAULT_LOG.error("Check changed gray configs error", e); + } finally { + ConfigExecutor.scheduleConfigChangeTask(this, PropertyUtil.getDumpChangeWorkerInterval(), + TimeUnit.MILLISECONDS); + LogUtil.DEFAULT_LOG.info("Next dump gray change will scheduled after {} milliseconds", + PropertyUtil.getDumpChangeWorkerInterval()); + + } + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpConfigHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpConfigHandler.java index 1ef08c6799a..e10b1b51dff 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpConfigHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpConfigHandler.java @@ -20,7 +20,6 @@ import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.listener.Subscriber; import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent; -import com.alibaba.nacos.config.server.service.AggrWhitelist; import com.alibaba.nacos.config.server.service.ClientIpWhiteList; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.SwitchService; @@ -44,58 +43,30 @@ public static boolean configDump(ConfigDumpEvent event) { final String group = event.getGroup(); final String namespaceId = event.getNamespaceId(); final String content = event.getContent(); - final String type = event.getType(); final long lastModified = event.getLastModifiedTs(); - //beta - if (event.isBeta()) { - boolean result = false; - if (event.isRemove()) { - result = ConfigCacheService.removeBeta(dataId, group, namespaceId); - if (result) { - ConfigTraceService.logDumpBetaEvent(dataId, group, namespaceId, null, lastModified, - event.getHandleIp(), ConfigTraceService.DUMP_TYPE_REMOVE_OK, - System.currentTimeMillis() - lastModified, 0); - } - return result; - } else { - result = ConfigCacheService.dumpBeta(dataId, group, namespaceId, content, lastModified, - event.getBetaIps(), event.getEncryptedDataKey()); - if (result) { - ConfigTraceService.logDumpBetaEvent(dataId, group, namespaceId, null, lastModified, - event.getHandleIp(), ConfigTraceService.DUMP_TYPE_OK, - System.currentTimeMillis() - lastModified, content.length()); - } - } - - return result; - } - - //tag - if (StringUtils.isNotBlank(event.getTag())) { + + //gray + if (StringUtils.isNotBlank(event.getGrayName())) { // - boolean result; + boolean result = false; if (!event.isRemove()) { - result = ConfigCacheService.dumpTag(dataId, group, namespaceId, event.getTag(), content, lastModified, - event.getEncryptedDataKey()); + result = ConfigCacheService.dumpGray(dataId, group, namespaceId, event.getGrayName(), + event.getGrayRule(), content, lastModified, event.getEncryptedDataKey()); if (result) { - ConfigTraceService.logDumpTagEvent(dataId, group, namespaceId, event.getTag(), null, lastModified, - event.getHandleIp(), ConfigTraceService.DUMP_TYPE_OK, + ConfigTraceService.logDumpGrayNameEvent(dataId, group, namespaceId, event.getGrayName(), null, + lastModified, event.getHandleIp(), ConfigTraceService.DUMP_TYPE_OK, System.currentTimeMillis() - lastModified, content.length()); } } else { - result = ConfigCacheService.removeTag(dataId, group, namespaceId, event.getTag()); + result = ConfigCacheService.removeGray(dataId, group, namespaceId, event.getGrayName()); if (result) { - ConfigTraceService.logDumpTagEvent(dataId, group, namespaceId, event.getTag(), null, lastModified, - event.getHandleIp(), ConfigTraceService.DUMP_TYPE_REMOVE_OK, + ConfigTraceService.logDumpGrayNameEvent(dataId, group, namespaceId, event.getGrayName(), null, + lastModified, event.getHandleIp(), ConfigTraceService.DUMP_TYPE_REMOVE_OK, System.currentTimeMillis() - lastModified, 0); } } - return result; - } - //default - if (dataId.equals(AggrWhitelist.AGGRIDS_METADATA)) { - AggrWhitelist.load(content); + return result; } if (dataId.equals(ClientIpWhiteList.CLIENT_IP_WHITELIST_METADATA)) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpRequest.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpRequest.java index 54ad18c9454..8d432bd6fb9 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpRequest.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpRequest.java @@ -19,6 +19,7 @@ /** * dump request. + * * @author shiyiyue */ public class DumpRequest { @@ -29,11 +30,7 @@ public class DumpRequest { String tenant; - private boolean isBeta; - - private boolean isBatch; - - private String tag; + String grayName; private long lastModifiedTs; @@ -63,30 +60,6 @@ public void setTenant(String tenant) { this.tenant = tenant; } - public boolean isBeta() { - return isBeta; - } - - public void setBeta(boolean beta) { - isBeta = beta; - } - - public boolean isBatch() { - return isBatch; - } - - public void setBatch(boolean batch) { - isBatch = batch; - } - - public String getTag() { - return tag; - } - - public void setTag(String tag) { - this.tag = tag; - } - public long getLastModifiedTs() { return lastModifiedTs; } @@ -99,17 +72,26 @@ public String getSourceIp() { return sourceIp; } + public String getGrayName() { + return grayName; + } + + public void setGrayName(String grayName) { + this.grayName = grayName; + } + public void setSourceIp(String sourceIp) { this.sourceIp = sourceIp; } /** * create dump request. - * @param dataId dataId. - * @param group group. - * @param tenant tenant. + * + * @param dataId dataId. + * @param group group. + * @param tenant tenant. * @param lastModifiedTs lastModifiedTs. - * @param sourceIp sourceIp. + * @param sourceIp sourceIp. * @return */ public static DumpRequest create(String dataId, String group, String tenant, long lastModifiedTs, String sourceIp) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java index 5a5ec201173..37c4d5778e4 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java @@ -23,22 +23,16 @@ import com.alibaba.nacos.common.notify.listener.Subscriber; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.manager.TaskManager; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; -import com.alibaba.nacos.config.server.service.dump.processor.DumpAllBetaProcessor; +import com.alibaba.nacos.config.server.service.dump.processor.DumpAllGrayProcessor; import com.alibaba.nacos.config.server.service.dump.processor.DumpAllProcessor; -import com.alibaba.nacos.config.server.service.dump.processor.DumpAllTagProcessor; import com.alibaba.nacos.config.server.service.dump.processor.DumpProcessor; -import com.alibaba.nacos.config.server.service.dump.task.DumpAllBetaTask; -import com.alibaba.nacos.config.server.service.dump.task.DumpAllTagTask; +import com.alibaba.nacos.config.server.service.dump.task.DumpAllGrayTask; import com.alibaba.nacos.config.server.service.dump.task.DumpAllTask; import com.alibaba.nacos.config.server.service.dump.task.DumpTask; -import com.alibaba.nacos.config.server.service.merge.MergeDatumService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.config.server.utils.ConfigExecutor; import com.alibaba.nacos.config.server.utils.GroupKey2; @@ -53,7 +47,6 @@ import org.slf4j.LoggerFactory; import java.sql.Timestamp; -import java.util.List; import java.util.Random; import java.util.concurrent.TimeUnit; @@ -73,9 +66,7 @@ public abstract class DumpService { protected DumpAllProcessor dumpAllProcessor; - protected DumpAllBetaProcessor dumpAllBetaProcessor; - - protected DumpAllTagProcessor dumpAllTagProcessor; + protected DumpAllGrayProcessor dumpAllGrayProcessor; protected ConfigInfoPersistService configInfoPersistService; @@ -83,13 +74,7 @@ public abstract class DumpService { protected HistoryConfigInfoPersistService historyConfigInfoPersistService; - protected ConfigInfoAggrPersistService configInfoAggrPersistService; - - protected ConfigInfoBetaPersistService configInfoBetaPersistService; - - protected ConfigInfoTagPersistService configInfoTagPersistService; - - protected MergeDatumService mergeDatumService; + protected ConfigInfoGrayPersistService configInfoGrayPersistService; protected final ServerMemberManager memberManager; @@ -111,12 +96,6 @@ public abstract class DumpService { int total = 0; - private static final String BETA_TABLE_NAME = "config_info_beta"; - - private static final String TAG_TABLE_NAME = "config_info_tag"; - - private int retentionDays = 30; - /** * Here you inject the dependent objects constructively, ensuring that some of the dependent functionality is * initialized ahead of time. @@ -126,23 +105,15 @@ public abstract class DumpService { public DumpService(ConfigInfoPersistService configInfoPersistService, NamespacePersistService namespacePersistService, HistoryConfigInfoPersistService historyConfigInfoPersistService, - ConfigInfoAggrPersistService configInfoAggrPersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService, - ConfigInfoTagPersistService configInfoTagPersistService, MergeDatumService mergeDatumService, - ServerMemberManager memberManager) { + ConfigInfoGrayPersistService configInfoGrayPersistService, ServerMemberManager memberManager) { this.configInfoPersistService = configInfoPersistService; + this.configInfoGrayPersistService = configInfoGrayPersistService; this.namespacePersistService = namespacePersistService; this.historyConfigInfoPersistService = historyConfigInfoPersistService; - this.configInfoAggrPersistService = configInfoAggrPersistService; - this.configInfoBetaPersistService = configInfoBetaPersistService; - this.configInfoTagPersistService = configInfoTagPersistService; - this.mergeDatumService = mergeDatumService; this.memberManager = memberManager; - this.processor = new DumpProcessor(this.configInfoPersistService, this.configInfoBetaPersistService, - this.configInfoTagPersistService); + this.processor = new DumpProcessor(this.configInfoPersistService, this.configInfoGrayPersistService); this.dumpAllProcessor = new DumpAllProcessor(this.configInfoPersistService); - this.dumpAllBetaProcessor = new DumpAllBetaProcessor(this.configInfoBetaPersistService); - this.dumpAllTagProcessor = new DumpAllTagProcessor(this.configInfoTagPersistService); + this.dumpAllGrayProcessor = new DumpAllGrayProcessor(this.configInfoGrayPersistService); this.dumpTaskMgr = new TaskManager("com.alibaba.nacos.server.DumpTaskManager"); this.dumpTaskMgr.setDefaultTaskProcessor(processor); @@ -150,9 +121,6 @@ public DumpService(ConfigInfoPersistService configInfoPersistService, this.dumpAllTaskMgr.setDefaultTaskProcessor(dumpAllProcessor); this.dumpAllTaskMgr.addProcessor(DumpAllTask.TASK_ID, dumpAllProcessor); - this.dumpAllTaskMgr.addProcessor(DumpAllBetaTask.TASK_ID, dumpAllBetaProcessor); - this.dumpAllTaskMgr.addProcessor(DumpAllTagTask.TASK_ID, dumpAllTagProcessor); - DynamicDataSource.getInstance().getDataSource(); NotifyCenter.registerSubscriber(new Subscriber() { @@ -173,12 +141,9 @@ void handleConfigDataChange(Event event) { // Generate ConfigDataChangeEvent concurrently if (event instanceof ConfigDataChangeEvent) { ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event; - DumpRequest dumpRequest = DumpRequest.create(evt.dataId, evt.group, evt.tenant, evt.lastModifiedTs, NetUtils.localIP()); - dumpRequest.setBeta(evt.isBeta); - dumpRequest.setBatch(evt.isBatch); - dumpRequest.setTag(evt.tag); + dumpRequest.setGrayName(evt.grayName); DumpService.this.dump(dumpRequest); } } @@ -230,24 +195,13 @@ public void run() { } /** - * dump all beta processor runner. + * dump all gray processor runner. */ - class DumpAllBetaProcessorRunner implements Runnable { + class DumpAllGrayProcessorRunner implements Runnable { @Override public void run() { - dumpAllTaskMgr.addTask(DumpAllBetaTask.TASK_ID, new DumpAllBetaTask()); - } - } - - /** - * dump all tag processor runner. - */ - class DumpAllTagProcessorRunner implements Runnable { - - @Override - public void run() { - dumpAllTaskMgr.addTask(DumpAllTagTask.TASK_ID, new DumpAllTagTask()); + dumpAllTaskMgr.addTask(DumpAllGrayTask.TASK_ID, new DumpAllGrayTask()); } } @@ -262,30 +216,10 @@ protected void dumpOperate() throws NacosException { try { dumpAllConfigInfoOnStartup(dumpAllProcessor); - // update Beta cache - LogUtil.DEFAULT_LOG.info("start clear all config-info-beta."); - ConfigDiskServiceFactory.getInstance().clearAllBeta(); - if (namespacePersistService.isExistTable(BETA_TABLE_NAME)) { - dumpAllBetaProcessor.process(new DumpAllBetaTask()); - } - // update Tag cache - LogUtil.DEFAULT_LOG.info("start clear all config-info-tag."); - ConfigDiskServiceFactory.getInstance().clearAllTag(); - if (namespacePersistService.isExistTable(TAG_TABLE_NAME)) { - dumpAllTagProcessor.process(new DumpAllTagTask()); - } + LogUtil.DEFAULT_LOG.info("start clear all config-info-gray."); + ConfigDiskServiceFactory.getInstance().clearAllGray(); + dumpAllGrayProcessor.process(new DumpAllGrayTask()); - // add to dump aggr - List configList = configInfoAggrPersistService.findAllAggrGroup(); - if (configList != null && !configList.isEmpty()) { - total = configList.size(); - List> splitList = mergeDatumService.splitList(configList, - INIT_THREAD_COUNT); - for (List list : splitList) { - mergeDatumService.executeConfigsMerge(list); - } - LOGGER.info("server start, schedule merge end."); - } } catch (Exception e) { LogUtil.FATAL_LOG.error( "Nacos Server did not start because dumpservice bean construction failure :\n" + e); @@ -301,17 +235,17 @@ protected void dumpOperate() throws NacosException { ConfigExecutor.scheduleConfigTask(new DumpAllProcessorRunner(), initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES); - - ConfigExecutor.scheduleConfigTask(new DumpAllBetaProcessorRunner(), initialDelay, + ConfigExecutor.scheduleConfigTask(new DumpAllGrayProcessorRunner(), initialDelay, DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES); - ConfigExecutor.scheduleConfigTask(new DumpAllTagProcessorRunner(), initialDelay, - DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES); ConfigExecutor.scheduleConfigChangeTask( new DumpChangeConfigWorker(this.configInfoPersistService, this.historyConfigInfoPersistService, currentTime), random.nextInt((int) PropertyUtil.getDumpChangeWorkerInterval()), TimeUnit.MILLISECONDS); - + ConfigExecutor.scheduleConfigChangeTask( + new DumpChangeGrayConfigWorker(this.configInfoGrayPersistService, currentTime, + this.historyConfigInfoPersistService), + random.nextInt((int) PropertyUtil.getDumpChangeWorkerInterval()), TimeUnit.MILLISECONDS); } HistoryConfigCleaner cleaner = HistoryConfigCleanerManager.getHistoryConfigCleaner( @@ -342,15 +276,9 @@ private void dumpAllConfigInfoOnStartup(DumpAllProcessor dumpAllProcessor) { * @param dumpRequest dumpRequest. */ public void dump(DumpRequest dumpRequest) { - if (dumpRequest.isBeta()) { - dumpBeta(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(), - dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp()); - } else if (dumpRequest.isBatch()) { - dumpBatch(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(), - dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp()); - } else if (StringUtils.isNotBlank(dumpRequest.getTag())) { - dumpTag(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(), dumpRequest.getTag(), - dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp()); + if (StringUtils.isNotBlank(dumpRequest.getGrayName())) { + dumpGray(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(), + dumpRequest.getGrayName(), dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp()); } else { dumpFormal(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(), dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp()); @@ -369,59 +297,27 @@ public void dump(DumpRequest dumpRequest) { private void dumpFormal(String dataId, String group, String tenant, long lastModified, String handleIp) { String groupKey = GroupKey2.getKey(dataId, group, tenant); String taskKey = groupKey; - dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, false, false, false, null, lastModified, handleIp)); + dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, null, lastModified, handleIp)); DUMP_LOG.info("[dump] add formal task. groupKey={}", groupKey); } /** - * dump beta. - * - * @param dataId dataId. - * @param group group. - * @param tenant tenant. - * @param lastModified lastModified. - * @param handleIp handleIp. - */ - private void dumpBeta(String dataId, String group, String tenant, long lastModified, String handleIp) { - String groupKey = GroupKey2.getKey(dataId, group, tenant); - String taskKey = groupKey + "+beta"; - dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, true, false, false, null, lastModified, handleIp)); - DUMP_LOG.info("[dump] add beta task. groupKey={}", groupKey); - - } - - /** - * dump batch. - * - * @param dataId dataId. - * @param group group. - * @param tenant tenant. - * @param lastModified lastModified. - * @param handleIp handleIp. - */ - private void dumpBatch(String dataId, String group, String tenant, long lastModified, String handleIp) { - String groupKey = GroupKey2.getKey(dataId, group, tenant); - String taskKey = groupKey + "+batch"; - dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, false, true, false, null, lastModified, handleIp)); - DUMP_LOG.info("[dump] add batch task. groupKey={}", dataId + "+" + group); - } - - /** - * dump tag. + * dump gray. * * @param dataId dataId. * @param group group. * @param tenant tenant. - * @param tag tag. + * @param grayName grayName. * @param lastModified lastModified. * @param handleIp handleIp. */ - private void dumpTag(String dataId, String group, String tenant, String tag, long lastModified, String handleIp) { + private void dumpGray(String dataId, String group, String tenant, String grayName, long lastModified, + String handleIp) { String groupKey = GroupKey2.getKey(dataId, group, tenant); - String taskKey = groupKey + "+tag+" + tag; - dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, false, false, true, tag, lastModified, handleIp)); - DUMP_LOG.info("[dump] add tag task. groupKey={},tag={}", groupKey, tag); + String taskKey = groupKey + "+gray+" + grayName; + dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, grayName, lastModified, handleIp)); + DUMP_LOG.info("[dump] add gray task. groupKey={},grayName={}", groupKey, grayName); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/EmbeddedDumpService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/EmbeddedDumpService.java index 4895cbdf13c..5f9b814e75b 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/EmbeddedDumpService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/EmbeddedDumpService.java @@ -20,20 +20,17 @@ import com.alibaba.nacos.common.utils.Observer; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.ThreadUtils; -import com.alibaba.nacos.config.server.service.merge.MergeDatumService; -import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage; -import com.alibaba.nacos.core.namespace.repository.NamespacePersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.consistency.ProtocolMetaData; import com.alibaba.nacos.consistency.cp.CPProtocol; import com.alibaba.nacos.consistency.cp.MetadataKey; import com.alibaba.nacos.core.cluster.ServerMemberManager; import com.alibaba.nacos.core.distributed.ProtocolManager; +import com.alibaba.nacos.core.namespace.repository.NamespacePersistService; import com.alibaba.nacos.core.utils.GlobalExecutor; +import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage; import com.alibaba.nacos.persistence.constants.PersistenceConstant; import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; import com.alibaba.nacos.sys.env.EnvUtil; @@ -76,13 +73,9 @@ public class EmbeddedDumpService extends DumpService { public EmbeddedDumpService(ConfigInfoPersistService configInfoPersistService, NamespacePersistService namespacePersistService, HistoryConfigInfoPersistService historyConfigInfoPersistService, - ConfigInfoAggrPersistService configInfoAggrPersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService, - ConfigInfoTagPersistService configInfoTagPersistService, MergeDatumService mergeDatumService, + ConfigInfoGrayPersistService configInfoGrayPersistService, ServerMemberManager memberManager, ProtocolManager protocolManager) { - super(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService, - configInfoAggrPersistService, configInfoBetaPersistService, configInfoTagPersistService, - mergeDatumService, memberManager); + super(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService, configInfoGrayPersistService, memberManager); this.protocolManager = protocolManager; } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/ExternalDumpService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/ExternalDumpService.java index 3b2b20fba1d..3a6b3e94e1c 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/ExternalDumpService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/ExternalDumpService.java @@ -16,15 +16,12 @@ package com.alibaba.nacos.config.server.service.dump; -import com.alibaba.nacos.config.server.service.merge.MergeDatumService; -import com.alibaba.nacos.core.namespace.repository.NamespacePersistService; -import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.core.cluster.ServerMemberManager; +import com.alibaba.nacos.core.namespace.repository.NamespacePersistService; +import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; @@ -38,7 +35,7 @@ */ @Conditional(ConditionOnExternalStorage.class) @Component -@DependsOn({"rpcConfigChangeNotifier"}) +@DependsOn({"rpcConfigChangeNotifier", "configGrayModelMigrateService"}) public class ExternalDumpService extends DumpService { /** @@ -50,13 +47,9 @@ public class ExternalDumpService extends DumpService { public ExternalDumpService(ConfigInfoPersistService configInfoPersistService, NamespacePersistService namespacePersistService, HistoryConfigInfoPersistService historyConfigInfoPersistService, - ConfigInfoAggrPersistService configInfoAggrPersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService, - ConfigInfoTagPersistService configInfoTagPersistService, MergeDatumService mergeDatumService, + ConfigInfoGrayPersistService configInfoGrayPersistService, ServerMemberManager memberManager) { - super(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService, - configInfoAggrPersistService, configInfoBetaPersistService, configInfoTagPersistService, - mergeDatumService, memberManager); + super(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService, configInfoGrayPersistService, memberManager); } @PostConstruct diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskService.java index 4983704872e..97169574013 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskService.java @@ -35,57 +35,49 @@ public interface ConfigDiskService { * @throws IOException io exception. */ void saveToDisk(String dataId, String group, String tenant, String content) throws IOException; - - /** - * Save beta information to disk. - * - * @param dataId dataId. - * @param group group. - * @param tenant tenant. - * @param content content. - * @throws IOException io exception. - */ - void saveBetaToDisk(String dataId, String group, String tenant, String content) throws IOException; /** - * Save tag information to disk. + * Save gray information to disk. * * @param dataId dataId. * @param group group. * @param tenant tenant. - * @param tag tag. + * @param grayName grayName. * @param content content. * @throws IOException io exception. */ - void saveTagToDisk(String dataId, String group, String tenant, String tag, String content) throws IOException; + void saveGrayToDisk(String dataId, String group, String tenant, String grayName, String content) throws IOException; /** - * Deletes configuration files on disk. + * Deletes gray configuration files on disk. * * @param dataId dataId. * @param group group. * @param tenant tenant. + * @param grayName grayName. */ - void removeConfigInfo(String dataId, String group, String tenant); + void removeConfigInfo4Gray(String dataId, String group, String tenant, String grayName); /** - * Deletes beta configuration files on disk. + * Returns the content of the gray cache file in server. * * @param dataId dataId. * @param group group. * @param tenant tenant. + * @param grayName grayName. + * @return gray content, null if not exist. + * @throws IOException io exception. */ - void removeConfigInfo4Beta(String dataId, String group, String tenant); + String getGrayContent(String dataId, String group, String tenant, String grayName) throws IOException; /** - * Deletes tag configuration files on disk. + * Deletes configuration files on disk. * * @param dataId dataId. * @param group group. * @param tenant tenant. - * @param tag tag. */ - void removeConfigInfo4Tag(String dataId, String group, String tenant, String tag); + void removeConfigInfo(String dataId, String group, String tenant); /** * Returns the content of the cache file in server. @@ -98,42 +90,14 @@ public interface ConfigDiskService { */ String getContent(String dataId, String group, String tenant) throws IOException; - /** - * Returns the beta content of cache file in server. - * - * @param dataId dataId. - * @param group group. - * @param tenant tenant. - * @return content, null if not exist. - * @throws IOException io exception. - */ - String getBetaContent(String dataId, String group, String tenant) throws IOException; - - /** - * Returns the path of the tag cache file in server. - * - * @param dataId dataId. - * @param group group. - * @param tenant tenant. - * @param tag tag. - * @return tag content, null if not exist. - * @throws IOException io exception. - */ - String getTagContent(String dataId, String group, String tenant, String tag) throws IOException; - /** * Clear all config file. */ void clearAll(); /** - * Clear all beta config file. - */ - void clearAllBeta(); - - /** - * Clear all tag config file. + * Clear all gray config file. */ - void clearAllTag(); + void clearAllGray(); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskService.java index 09fa0052a7c..45dc2982e2c 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskService.java @@ -45,17 +45,9 @@ public class ConfigRawDiskService implements ConfigDiskService { private static final String TENANT_BASE_DIR = File.separator + "data" + File.separator + "tenant-config-data"; - private static final String BETA_DIR = File.separator + "data" + File.separator + "beta-data"; + private static final String GRAY_DIR = File.separator + "data" + File.separator + "gray-data"; - private static final String TENANT_BETA_DIR = File.separator + "data" + File.separator + "tenant-beta-data"; - - private static final String TAG_DIR = File.separator + "data" + File.separator + "tag-data"; - - private static final String TENANT_TAG_DIR = File.separator + "data" + File.separator + "tenant-tag-data"; - - private static final String BATCH_DIR = File.separator + "data" + File.separator + "batch-data"; - - private static final String TENANT_BATCH_DIR = File.separator + "data" + File.separator + "tenant-batch-data"; + private static final String TENANT_GRAY_DIR = File.separator + "data" + File.separator + "tenant-gray-data"; /** * Save configuration information to disk. @@ -91,36 +83,11 @@ static File targetFile(String dataId, String group, String tenant) { } /** - * Returns the path of cache file in server. - */ - private static File targetBetaFile(String dataId, String group, String tenant) { - try { - ParamUtils.checkParam(dataId, group, tenant); - } catch (Exception e) { - throw new NacosRuntimeException(NacosException.CLIENT_INVALID_PARAM, "parameter is invalid."); - } - // fix https://github.com/alibaba/nacos/issues/10067 - dataId = PathEncoderManager.getInstance().encode(dataId); - group = PathEncoderManager.getInstance().encode(group); - tenant = PathEncoderManager.getInstance().encode(tenant); - File file = null; - if (StringUtils.isBlank(tenant)) { - file = new File(EnvUtil.getNacosHome(), BETA_DIR); - } else { - file = new File(EnvUtil.getNacosHome(), TENANT_BETA_DIR); - file = new File(file, tenant); - } - file = new File(file, group); - file = new File(file, dataId); - return file; - } - - /** - * Returns the path of the tag cache file in server. + * Returns the path of the gray cache file in server. */ - private static File targetTagFile(String dataId, String group, String tenant, String tag) { + private static File targetGrayFile(String dataId, String group, String tenant, String grayName) { try { - ParamUtils.checkParam(tag); + ParamUtils.checkParam(grayName); ParamUtils.checkParam(dataId, group, tenant); } catch (Exception e) { throw new NacosRuntimeException(NacosException.CLIENT_INVALID_PARAM, "parameter is invalid."); @@ -129,34 +96,34 @@ private static File targetTagFile(String dataId, String group, String tenant, St dataId = PathEncoderManager.getInstance().encode(dataId); group = PathEncoderManager.getInstance().encode(group); tenant = PathEncoderManager.getInstance().encode(tenant); + File file = null; if (StringUtils.isBlank(tenant)) { - file = new File(EnvUtil.getNacosHome(), TAG_DIR); + file = new File(EnvUtil.getNacosHome(), GRAY_DIR); } else { - file = new File(EnvUtil.getNacosHome(), TENANT_TAG_DIR); + file = new File(EnvUtil.getNacosHome(), TENANT_GRAY_DIR); file = new File(file, tenant); } file = new File(file, group); file = new File(file, dataId); - file = new File(file, tag); + file = new File(file, grayName); return file; } /** - * Save beta information to disk. + * Returns the path of the gray content cache file in server. */ - public void saveBetaToDisk(String dataId, String group, String tenant, String content) throws IOException { - File targetFile = targetBetaFile(dataId, group, tenant); - FileUtils.writeStringToFile(targetFile, content, ENCODE_UTF8); + private static File targetGrayContentFile(String dataId, String group, String tenant, String grayName) { + return targetGrayFile(dataId, group, tenant, grayName); } /** - * Save tag information to disk. + * Save gray information to disk. */ - public void saveTagToDisk(String dataId, String group, String tenant, String tag, String content) + public void saveGrayToDisk(String dataId, String group, String tenant, String grayName, String content) throws IOException { - File targetFile = targetTagFile(dataId, group, tenant, tag); - FileUtils.writeStringToFile(targetFile, content, ENCODE_UTF8); + File targetGrayContentFile = targetGrayContentFile(dataId, group, tenant, grayName); + FileUtils.writeStringToFile(targetGrayContentFile, content, ENCODE_UTF8); } /** @@ -167,17 +134,10 @@ public void removeConfigInfo(String dataId, String group, String tenant) { } /** - * Deletes beta configuration files on disk. - */ - public void removeConfigInfo4Beta(String dataId, String group, String tenant) { - FileUtils.deleteQuietly(targetBetaFile(dataId, group, tenant)); - } - - /** - * Deletes tag configuration files on disk. + * Deletes gray configuration files on disk. */ - public void removeConfigInfo4Tag(String dataId, String group, String tenant, String tag) { - FileUtils.deleteQuietly(targetTagFile(dataId, group, tenant, tag)); + public void removeConfigInfo4Gray(String dataId, String group, String tenant, String grayName) { + FileUtils.deleteQuietly(targetGrayContentFile(dataId, group, tenant, grayName)); } private static String file2String(File file) throws IOException { @@ -188,19 +148,10 @@ private static String file2String(File file) throws IOException { } /** - * Returns the path of cache file in server. + * Returns the content of the gray cache file in server. */ - public String getBetaContent(String dataId, String group, String tenant) throws IOException { - File file = targetBetaFile(dataId, group, tenant); - return file2String(file); - } - - /** - * Returns the path of the tag cache file in server. - */ - public String getTagContent(String dataId, String group, String tenant, String tag) throws IOException { - File file = targetTagFile(dataId, group, tenant, tag); - return file2String(file); + public String getGrayContent(String dataId, String group, String tenant, String grayName) throws IOException { + return file2String(targetGrayContentFile(dataId, group, tenant, grayName)); } public String getContent(String dataId, String group, String tenant) throws IOException { @@ -239,39 +190,21 @@ public void clearAll() { } /** - * Clear all beta config file. - */ - public void clearAllBeta() { - File file = new File(EnvUtil.getNacosHome(), BETA_DIR); - if (!file.exists() || FileUtils.deleteQuietly(file)) { - LogUtil.DEFAULT_LOG.info("clear all config-info-beta success."); - } else { - LogUtil.DEFAULT_LOG.warn("clear all config-info-beta failed."); - } - File fileTenant = new File(EnvUtil.getNacosHome(), TENANT_BETA_DIR); - if (!fileTenant.exists() || FileUtils.deleteQuietly(fileTenant)) { - LogUtil.DEFAULT_LOG.info("clear all config-info-beta-tenant success."); - } else { - LogUtil.DEFAULT_LOG.warn("clear all config-info-beta-tenant failed."); - } - } - - /** - * Clear all tag config file. + * Clear all gray config file. */ - public void clearAllTag() { - File file = new File(EnvUtil.getNacosHome(), TAG_DIR); + public void clearAllGray() { + File file = new File(EnvUtil.getNacosHome(), GRAY_DIR); if (!file.exists() || FileUtils.deleteQuietly(file)) { - LogUtil.DEFAULT_LOG.info("clear all config-info-tag success."); + LogUtil.DEFAULT_LOG.info("clear all config-info-gray success."); } else { - LogUtil.DEFAULT_LOG.warn("clear all config-info-tag failed."); + LogUtil.DEFAULT_LOG.warn("clear all config-info-gray failed."); } - File fileTenant = new File(EnvUtil.getNacosHome(), TENANT_TAG_DIR); + File fileTenant = new File(EnvUtil.getNacosHome(), TENANT_GRAY_DIR); if (!fileTenant.exists() || FileUtils.deleteQuietly(fileTenant)) { - LogUtil.DEFAULT_LOG.info("clear all config-info-tag-tenant success."); + LogUtil.DEFAULT_LOG.info("clear all config-info-gray-tenant success."); } else { - LogUtil.DEFAULT_LOG.warn("clear all config-info-tag-tenant failed."); + LogUtil.DEFAULT_LOG.warn("clear all config-info-gray-tenant failed."); } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRocksDbDiskService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRocksDbDiskService.java index 0eb85f98be6..0da0cc40284 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRocksDbDiskService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRocksDbDiskService.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.config.server.service.dump.disk; +import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.sys.env.EnvUtil; @@ -32,6 +33,7 @@ import java.util.Map; import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; +import static com.alibaba.nacos.config.server.constant.Constants.NULL; /** * config rocks db disk service. @@ -45,11 +47,7 @@ public class ConfigRocksDbDiskService implements ConfigDiskService { private static final String BASE_DIR = ROCKSDB_DATA + "config-data"; - private static final String BETA_DIR = ROCKSDB_DATA + "beta-data"; - - private static final String TAG_DIR = ROCKSDB_DATA + "tag-data"; - - private static final String BATCH_DIR = ROCKSDB_DATA + "batch-data"; + private static final String GRAY_DIR = ROCKSDB_DATA + "gray-data"; private static final long DEFAULT_WRITE_BUFFER_MB = 32; @@ -79,13 +77,19 @@ private void deleteDirIfExist(String dir) { public ConfigRocksDbDiskService() { createDirIfNotExist(BASE_DIR); - createDirIfNotExist(BETA_DIR); - createDirIfNotExist(TAG_DIR); - createDirIfNotExist(BATCH_DIR); + createDirIfNotExist(GRAY_DIR); + } private byte[] getKeyByte(String dataId, String group, String tenant, String tag) throws IOException { String[] keys = new String[] {dataId, group, tenant, tag}; + return getKeyByte(keys); + } + + private byte[] getKeyByte(String... keys) throws IOException { + if (keys == null || keys.length == 0) { + return NULL.getBytes(ENCODE_UTF8); + } StringBuilder stringBuilder = new StringBuilder(); for (String key : keys) { if (StringUtils.isBlank(key)) { @@ -134,26 +138,30 @@ public void saveToDiskInner(String type, String dataId, String group, String ten } /** - * Save configuration information to disk. + * save config to disk. */ - public void saveToDisk(String dataId, String group, String tenant, String content) throws IOException { - saveToDiskInner(BASE_DIR, dataId, group, tenant, content); + public void saveGrayToDiskInner(String type, String dataId, String group, String tenant, String grayName, + String content) throws IOException { + try { + initAndGetDB(type).put(getKeyByte(dataId, group, tenant, grayName), content.getBytes(ENCODE_UTF8)); + } catch (RocksDBException e) { + throw new IOException(e); + } } /** - * Save beta information to disk. + * Save configuration information to disk. */ - public void saveBetaToDisk(String dataId, String group, String tenant, String content) throws IOException { - saveToDiskInner(BETA_DIR, dataId, group, tenant, content); - + public void saveToDisk(String dataId, String group, String tenant, String content) throws IOException { + saveToDiskInner(BASE_DIR, dataId, group, tenant, content); } /** * Save tag information to disk. */ - public void saveTagToDisk(String dataId, String group, String tenant, String tag, String content) + public void saveGrayToDisk(String dataId, String group, String tenant, String grayName, String content) throws IOException { - saveToDiskInner(TAG_DIR, dataId, group, tenant, tag, content); + saveGrayToDiskInner(GRAY_DIR, dataId, group, tenant, grayName, content); } @@ -165,17 +173,10 @@ public void removeConfigInfo(String dataId, String group, String tenant) { } /** - * Deletes beta configuration files on disk. + * Deletes gray configuration files on disk. */ - public void removeConfigInfo4Beta(String dataId, String group, String tenant) { - removeContentInner(BETA_DIR, dataId, group, tenant, null); - } - - /** - * Deletes tag configuration files on disk. - */ - public void removeConfigInfo4Tag(String dataId, String group, String tenant, String tag) { - removeContentInner(TAG_DIR, dataId, group, tenant, tag); + public void removeConfigInfo4Gray(String dataId, String group, String tenant, String grayName) { + removeGrayInner(GRAY_DIR, dataId, group, tenant, grayName); } @@ -186,7 +187,7 @@ private String byte2String(byte[] bytes) throws IOException { return new String(bytes, ENCODE_UTF8); } - RocksDB initAndGetDB(String dir) throws RocksDBException { + RocksDB initAndGetDB(String dir) throws IOException, RocksDBException { if (rocksDbMap.containsKey(dir)) { return rocksDbMap.get(dir); } else { @@ -220,11 +221,11 @@ private String getContentInner(String type, String dataId, String group, String } } - private String getTagContentInner(String type, String dataId, String group, String tenant, String tag) + private String getGrayInner(String type, String dataId, String group, String tenant, String grayName) throws IOException { byte[] bytes = null; try { - bytes = initAndGetDB(type).get(getKeyByte(dataId, group, tenant, tag)); + bytes = initAndGetDB(type).get(getKeyByte(dataId, group, tenant, grayName)); return byte2String(bytes); } catch (RocksDBException e) { throw new IOException(e); @@ -240,24 +241,30 @@ private void removeContentInner(String type, String dataId, String group, String } } - /** - * Returns the path of cache file in server. - */ - public String getBetaContent(String dataId, String group, String tenant) throws IOException { - return getContentInner(BETA_DIR, dataId, group, tenant); + private void removeGrayInner(String type, String dataId, String group, String tenant, String grayName) { + try { + initAndGetDB(type).delete(getKeyByte(dataId, group, tenant, grayName)); + } catch (Exception e) { + LogUtil.DEFAULT_LOG.warn("Remove dir=[{}] config fail,dataId={},group={},tenant={},error={}", type, dataId, + group, tenant, e.getCause()); + } } /** - * Returns the path of the tag cache file in server. + * Returns the path of the gray content cache file in server. */ - public String getTagContent(String dataId, String group, String tenant, String tag) throws IOException { - return getTagContentInner(TAG_DIR, dataId, group, tenant, tag); + public String getGrayContent(String dataId, String group, String tenant, String grayName) throws IOException { + return getGrayInner(GRAY_DIR, dataId, group, tenant, grayName); } public String getContent(String dataId, String group, String tenant) throws IOException { return getContentInner(BASE_DIR, dataId, group, tenant); } + public String getLocalConfigMd5(String dataId, String group, String tenant, String encode) throws IOException { + return MD5Utils.md5Hex(getContentInner(BASE_DIR, dataId, group, tenant), encode); + } + Options createOptions(String dir) { DBOptions dbOptions = new DBOptions(); dbOptions.setMaxBackgroundJobs(Runtime.getRuntime().availableProcessors()); @@ -326,35 +333,19 @@ public void clearAll() { } /** - * Clear all beta config file. - */ - public void clearAllBeta() { - try { - if (rocksDbMap.containsKey(BETA_DIR)) { - rocksDbMap.get(BETA_DIR).close(); - RocksDB.destroyDB(EnvUtil.getNacosHome() + BETA_DIR, new Options()); - } - deleteDirIfExist(BETA_DIR); - LogUtil.DEFAULT_LOG.info("clear all config-info-beta success."); - } catch (RocksDBException e) { - LogUtil.DEFAULT_LOG.warn("clear all config-info-beta failed.", e); - } - } - - /** - * Clear all tag config file. + * Clear all gray config file. */ - public void clearAllTag() { + public void clearAllGray() { try { - if (rocksDbMap.containsKey(TAG_DIR)) { - rocksDbMap.get(TAG_DIR).close(); - RocksDB.destroyDB(EnvUtil.getNacosHome() + TAG_DIR, new Options()); + if (rocksDbMap.containsKey(GRAY_DIR)) { + rocksDbMap.get(GRAY_DIR).close(); + RocksDB.destroyDB(EnvUtil.getNacosHome() + GRAY_DIR, new Options()); } - deleteDirIfExist(TAG_DIR); - LogUtil.DEFAULT_LOG.info("clear all config-info-tag success."); + deleteDirIfExist(GRAY_DIR); + LogUtil.DEFAULT_LOG.info("clear all config-info-gray success."); } catch (RocksDBException e) { - LogUtil.DEFAULT_LOG.warn("clear all config-info-tag failed.", e); + LogUtil.DEFAULT_LOG.warn("clear all config-info-gray failed.", e); } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllBetaProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllBetaProcessor.java deleted file mode 100644 index 47b7aab0e5b..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllBetaProcessor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.dump.processor; - -import com.alibaba.nacos.common.task.NacosTask; -import com.alibaba.nacos.common.task.NacosTaskProcessor; -import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper; -import com.alibaba.nacos.config.server.service.ConfigCacheService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; -import com.alibaba.nacos.config.server.utils.GroupKey2; -import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.persistence.model.Page; - -import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG; - -/** - * Dump all beta processor. - * - * @author Nacos - * @author Wei.Wang - * @date 2020/7/5 12:18 PM - */ -public class DumpAllBetaProcessor implements NacosTaskProcessor { - - public DumpAllBetaProcessor(ConfigInfoBetaPersistService configInfoBetaPersistService) { - this.configInfoBetaPersistService = configInfoBetaPersistService; - } - - @Override - public boolean process(NacosTask task) { - int rowCount = configInfoBetaPersistService.configInfoBetaCount(); - int pageCount = (int) Math.ceil(rowCount * 1.0 / PAGE_SIZE); - - int actualRowCount = 0; - for (int pageNo = 1; pageNo <= pageCount; pageNo++) { - Page page = configInfoBetaPersistService.findAllConfigInfoBetaForDumpAll(pageNo, - PAGE_SIZE); - if (page != null) { - for (ConfigInfoBetaWrapper cf : page.getPageItems()) { - boolean result = ConfigCacheService.dumpBeta(cf.getDataId(), cf.getGroup(), cf.getTenant(), - cf.getContent(), cf.getLastModified(), cf.getBetaIps(), cf.getEncryptedDataKey()); - LogUtil.DUMP_LOG.info("[dump-all-beta-ok] result={}, {}, {}, length={}, md5={}", result, - GroupKey2.getKey(cf.getDataId(), cf.getGroup()), cf.getLastModified(), - cf.getContent().length(), cf.getMd5()); - } - - actualRowCount += page.getPageItems().size(); - DEFAULT_LOG.info("[all-dump-beta] {} / {}", actualRowCount, rowCount); - } - } - return true; - } - - static final int PAGE_SIZE = 1000; - - final ConfigInfoBetaPersistService configInfoBetaPersistService; -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllTagProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllGrayProcessor.java similarity index 61% rename from config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllTagProcessor.java rename to config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllGrayProcessor.java index 2e4e4e7dfc0..43dd5cf18af 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllTagProcessor.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllGrayProcessor.java @@ -18,53 +18,54 @@ import com.alibaba.nacos.common.task.NacosTask; import com.alibaba.nacos.common.task.NacosTaskProcessor; -import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper; -import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; import com.alibaba.nacos.config.server.service.ConfigCacheService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.LogUtil; +import com.alibaba.nacos.persistence.model.Page; import static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG; +import static com.alibaba.nacos.config.server.utils.PropertyUtil.getAllDumpPageSize; /** - * Dump all tag processor. + * Dump all gray processor. * * @author Nacos - * @date 2020/7/5 12:18 PM + * @datete 2024/02/20 */ -public class DumpAllTagProcessor implements NacosTaskProcessor { +public class DumpAllGrayProcessor implements NacosTaskProcessor { - public DumpAllTagProcessor(ConfigInfoTagPersistService configInfoTagPersistService) { - this.configInfoTagPersistService = configInfoTagPersistService; + public DumpAllGrayProcessor(ConfigInfoGrayPersistService configInfoGrayPersistService) { + this.configInfoGrayPersistService = configInfoGrayPersistService; } @Override public boolean process(NacosTask task) { - int rowCount = configInfoTagPersistService.configInfoTagCount(); + int rowCount = configInfoGrayPersistService.configInfoGrayCount(); int pageCount = (int) Math.ceil(rowCount * 1.0 / PAGE_SIZE); int actualRowCount = 0; for (int pageNo = 1; pageNo <= pageCount; pageNo++) { - Page page = configInfoTagPersistService.findAllConfigInfoTagForDumpAll(pageNo, PAGE_SIZE); + Page page = configInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(pageNo, PAGE_SIZE); if (page != null) { - for (ConfigInfoTagWrapper cf : page.getPageItems()) { + for (ConfigInfoGrayWrapper cf : page.getPageItems()) { boolean result = ConfigCacheService - .dumpTag(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getTag(), cf.getContent(), + .dumpGray(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getGrayName(), cf.getGrayRule(), cf.getContent(), cf.getLastModified(), cf.getEncryptedDataKey()); - LogUtil.DUMP_LOG.info("[dump-all-Tag-ok] result={}, {}, {}, length={}, md5={}", result, + LogUtil.DUMP_LOG.info("[dump-all-gray-ok] result={}, {}, {}, length={}, md5={}, grayName={}", result, GroupKey2.getKey(cf.getDataId(), cf.getGroup()), cf.getLastModified(), - cf.getContent().length(), cf.getMd5()); + cf.getContent().length(), cf.getMd5(), cf.getGrayName()); } actualRowCount += page.getPageItems().size(); - DEFAULT_LOG.info("[all-dump-tag] {} / {}", actualRowCount, rowCount); + DEFAULT_LOG.info("[all-dump-gray] {} / {}", actualRowCount, rowCount); } } return true; } - static final int PAGE_SIZE = 1000; + static final int PAGE_SIZE = getAllDumpPageSize(); - final ConfigInfoTagPersistService configInfoTagPersistService; + final ConfigInfoGrayPersistService configInfoGrayPersistService; } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessor.java index a6d245011c2..2c07dd8a2d5 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessor.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessor.java @@ -20,7 +20,6 @@ import com.alibaba.nacos.common.task.NacosTaskProcessor; import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.config.server.model.ConfigInfoWrapper; -import com.alibaba.nacos.config.server.service.AggrWhitelist; import com.alibaba.nacos.config.server.service.ClientIpWhiteList; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.SwitchService; @@ -54,7 +53,9 @@ public DumpAllProcessor(ConfigInfoPersistService configInfoPersistService) { @Override public boolean process(NacosTask task) { if (!(task instanceof DumpAllTask)) { - DEFAULT_LOG.error("[all-dump-error] ,invalid task type,DumpAllProcessor should process DumpAllTask type."); + DEFAULT_LOG.error( + "[all-dump-error] ,invalid task type {},DumpAllProcessor should process DumpAllTask type.", + task.getClass().getSimpleName()); return false; } DumpAllTask dumpAllTask = (DumpAllTask) task; @@ -106,9 +107,6 @@ public boolean process(NacosTask task) { if (cf == null) { continue; } - if (cf.getDataId().equals(AggrWhitelist.AGGRIDS_METADATA)) { - AggrWhitelist.load(cf.getContent()); - } if (cf.getDataId().equals(ClientIpWhiteList.CLIENT_IP_WHITELIST_METADATA)) { ClientIpWhiteList.load(cf.getContent()); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpProcessor.java index 8c5b2267feb..600ec730fd6 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpProcessor.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpProcessor.java @@ -19,15 +19,13 @@ import com.alibaba.nacos.common.task.NacosTask; import com.alibaba.nacos.common.task.NacosTaskProcessor; import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper; -import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoWrapper; import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent; import com.alibaba.nacos.config.server.service.dump.DumpConfigHandler; import com.alibaba.nacos.config.server.service.dump.task.DumpTask; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.LogUtil; @@ -43,16 +41,12 @@ public class DumpProcessor implements NacosTaskProcessor { final ConfigInfoPersistService configInfoPersistService; - final ConfigInfoBetaPersistService configInfoBetaPersistService; - - final ConfigInfoTagPersistService configInfoTagPersistService; + final ConfigInfoGrayPersistService configInfoGrayPersistService; public DumpProcessor(ConfigInfoPersistService configInfoPersistService, - ConfigInfoBetaPersistService configInfoBetaPersistService, - ConfigInfoTagPersistService configInfoTagPersistService) { + ConfigInfoGrayPersistService configInfoGrayPersistService) { this.configInfoPersistService = configInfoPersistService; - this.configInfoBetaPersistService = configInfoBetaPersistService; - this.configInfoTagPersistService = configInfoTagPersistService; + this.configInfoGrayPersistService = configInfoGrayPersistService; } @Override @@ -64,37 +58,26 @@ public boolean process(NacosTask task) { String tenant = pair[2]; long lastModifiedOut = dumpTask.getLastModified(); String handleIp = dumpTask.getHandleIp(); - boolean isBeta = dumpTask.isBeta(); - String tag = dumpTask.getTag(); + String grayName = dumpTask.getGrayName(); + ConfigDumpEvent.ConfigDumpEventBuilder build = ConfigDumpEvent.builder().namespaceId(tenant).dataId(dataId) - .group(group).isBeta(isBeta).tag(tag).handleIp(handleIp); + .group(group).grayName(grayName).handleIp(handleIp); String type = "formal"; - if (isBeta) { - type = "beta"; - } else if (StringUtils.isNotBlank(tag)) { - type = "tag-" + tag; + if (StringUtils.isNotBlank(grayName)) { + type = grayName; } LogUtil.DUMP_LOG.info("[dump] process {} task. groupKey={}", type, dumpTask.getGroupKey()); - if (isBeta) { - // if publish beta, then dump config, update beta cache - ConfigInfoBetaWrapper cf = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant); - build.remove(Objects.isNull(cf)); - build.betaIps(Objects.isNull(cf) ? null : cf.getBetaIps()); - build.content(Objects.isNull(cf) ? null : cf.getContent()); - build.type(Objects.isNull(cf) ? null : cf.getType()); - build.encryptedDataKey(Objects.isNull(cf) ? null : cf.getEncryptedDataKey()); - build.lastModifiedTs(Objects.isNull(cf) ? lastModifiedOut : cf.getLastModified()); - return DumpConfigHandler.configDump(build.build()); - } - - if (StringUtils.isNotBlank(tag)) { - ConfigInfoTagWrapper cf = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag); + if (StringUtils.isNotBlank(grayName)) { + ConfigInfoGrayWrapper cf = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant, + grayName); build.remove(Objects.isNull(cf)); build.content(Objects.isNull(cf) ? null : cf.getContent()); build.type(Objects.isNull(cf) ? null : cf.getType()); build.encryptedDataKey(Objects.isNull(cf) ? null : cf.getEncryptedDataKey()); build.lastModifiedTs(Objects.isNull(cf) ? lastModifiedOut : cf.getLastModified()); + build.grayName(grayName); + build.grayRule(Objects.isNull(cf) ? null : cf.getGrayRule()); return DumpConfigHandler.configDump(build.build()); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllGrayTask.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllGrayTask.java new file mode 100644 index 00000000000..dfdc4ee8c3d --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllGrayTask.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.dump.task; + +import com.alibaba.nacos.common.task.AbstractDelayTask; + +/** + * Dump all gray task. + * + * @author Nacos + * @date 2024/3/5 + */ +public class DumpAllGrayTask extends AbstractDelayTask { + + @Override + public void merge(AbstractDelayTask task) { + } + + public static final String TASK_ID = "dumpAllGrayConfigTask"; +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpTask.java b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpTask.java index 9de5ea4544f..ca83b45eea3 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpTask.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpTask.java @@ -25,19 +25,11 @@ */ public class DumpTask extends AbstractDelayTask { - public DumpTask(String groupKey, boolean isBeta, boolean isBatch, boolean isTag, String tag, long lastModified, - String handleIp) { + public DumpTask(String groupKey, String grayName, long lastModified, String handleIp) { this.groupKey = groupKey; this.lastModified = lastModified; this.handleIp = handleIp; - this.isBeta = isBeta; - if (isTag) { - this.tag = tag; - } else { - this.tag = null; - } - this.isBatch = isBatch; - + this.grayName = grayName; //retry interval: 1s setTaskInterval(1000L); } @@ -52,11 +44,7 @@ public void merge(AbstractDelayTask task) { final String handleIp; - final boolean isBeta; - - final String tag; - - final boolean isBatch; + final String grayName; public String getGroupKey() { return groupKey; @@ -70,16 +58,8 @@ public String getHandleIp() { return handleIp; } - public boolean isBeta() { - return isBeta; - } - - public String getTag() { - return tag; - } - - public boolean isBatch() { - return isBatch; + public String getGrayName() { + return grayName; } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDataTask.java b/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDataTask.java deleted file mode 100755 index 8ea2d2402d4..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDataTask.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.merge; - -import com.alibaba.nacos.common.task.AbstractDelayTask; - -/** - * Represents the task of aggregating data. - * - * @author jiuRen - */ -class MergeDataTask extends AbstractDelayTask { - - MergeDataTask(String dataId, String groupId, String tenant, String clientIp) { - this(dataId, groupId, tenant, null, clientIp); - } - - MergeDataTask(String dataId, String groupId, String tenant, String tag, String clientIp) { - this.dataId = dataId; - this.groupId = groupId; - this.tenant = tenant; - this.tag = tag; - this.clientIp = clientIp; - - // aggregation delay - setTaskInterval(DELAY); - setLastProcessTime(System.currentTimeMillis()); - } - - @Override - public void merge(AbstractDelayTask task) { - } - - public String getId() { - return toString(); - } - - @Override - public String toString() { - return "MergeTask[" + dataId + ", " + groupId + ", " + tenant + ", " + clientIp + "]"; - } - - public String getClientIp() { - return clientIp; - } - - static final long DELAY = 0L; - - final String dataId; - - final String groupId; - - final String tenant; - - final String tag; - - private final String clientIp; -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDatumService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDatumService.java deleted file mode 100644 index cb039bfe75d..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeDatumService.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.merge; - -import com.alibaba.nacos.common.utils.MD5Utils; -import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.constant.Constants; -import com.alibaba.nacos.config.server.manager.TaskManager; -import com.alibaba.nacos.config.server.model.ConfigInfo; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.config.server.service.ConfigCacheService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; -import com.alibaba.nacos.config.server.utils.ContentUtils; -import com.alibaba.nacos.config.server.utils.GroupKey; -import com.alibaba.nacos.core.distributed.ProtocolManager; -import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration; -import com.alibaba.nacos.persistence.constants.PersistenceConstant; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.sys.env.EnvUtil; -import com.alibaba.nacos.sys.utils.ApplicationUtils; -import com.alibaba.nacos.sys.utils.InetUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Data aggregation service. - * - *

Full aggregation at startup and single aggregation triggered by data modification. - * - * @author jiuRen - */ -@Service -public class MergeDatumService { - - private static final Logger LOGGER = LoggerFactory.getLogger(MergeDatumService.class); - - final TaskManager mergeTasks; - - static final int INIT_THREAD_COUNT = 40; - - static final AtomicInteger FINISHED = new AtomicInteger(); - - static int total = 0; - - private ConfigInfoPersistService configInfoPersistService; - - private ConfigInfoAggrPersistService configInfoAggrPersistService; - - @Autowired - public MergeDatumService(ConfigInfoPersistService configInfoPersistService, - ConfigInfoAggrPersistService configInfoAggrPersistService, - ConfigInfoTagPersistService configInfoTagPersistService) { - this.configInfoPersistService = configInfoPersistService; - this.configInfoAggrPersistService = configInfoAggrPersistService; - mergeTasks = new TaskManager("com.alibaba.nacos.MergeDatum"); - mergeTasks.setDefaultTaskProcessor( - new MergeTaskProcessor(configInfoPersistService, configInfoAggrPersistService, - configInfoTagPersistService, this)); - } - - /** - * splitList. - * - * @param list list to split. - * @param count count expect to be split. - * @return - */ - public List> splitList(List list, int count) { - List> result = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - result.add(new ArrayList<>()); - } - for (int i = 0; i < list.size(); i++) { - ConfigInfoChanged config = list.get(i); - result.get(i % count).add(config); - } - return result; - } - - /** - * Called after data changes to add aggregation tasks. - */ - public void addMergeTask(String dataId, String groupId, String tenant, String clientIp) { - if (!canExecute()) { - return; - } - MergeDataTask task = new MergeDataTask(dataId, groupId, tenant, clientIp); - mergeTasks.addTask(task.getId(), task); - } - - private boolean canExecute() { - if (!DatasourceConfiguration.isEmbeddedStorage()) { - return true; - } - if (EnvUtil.getStandaloneMode()) { - return true; - } - ProtocolManager protocolManager = ApplicationUtils.getBean(ProtocolManager.class); - return protocolManager.getCpProtocol().isLeader(PersistenceConstant.CONFIG_MODEL_RAFT_GROUP); - } - - void executeMergeConfigTask(List configInfoList, int pageSize) { - for (ConfigInfoChanged configInfo : configInfoList) { - String dataId = configInfo.getDataId(); - String group = configInfo.getGroup(); - String tenant = configInfo.getTenant(); - try { - List datumList = new ArrayList<>(); - int rowCount = configInfoAggrPersistService.aggrConfigInfoCount(dataId, group, tenant); - int pageCount = (int) Math.ceil(rowCount * 1.0 / pageSize); - for (int pageNo = 1; pageNo <= pageCount; pageNo++) { - Page page = configInfoAggrPersistService.findConfigInfoAggrByPage(dataId, group, - tenant, pageNo, pageSize); - if (page != null) { - datumList.addAll(page.getPageItems()); - LOGGER.info("[merge-query] {}, {}, size/total={}/{}", dataId, group, datumList.size(), - rowCount); - } - } - - // merge - if (datumList.size() > 0) { - ConfigInfo cf = MergeTaskProcessor.merge(dataId, group, tenant, datumList); - String aggrContent = cf.getContent(); - String localContentMD5 = ConfigCacheService.getContentMd5(GroupKey.getKey(dataId, group)); - String aggrConetentMD5 = MD5Utils.md5Hex(aggrContent, Constants.ENCODE); - - if (!StringUtils.equals(localContentMD5, aggrConetentMD5)) { - configInfoPersistService.insertOrUpdate(null, null, cf, null); - LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group, - datumList.size(), cf.getContent().length(), cf.getMd5(), - ContentUtils.truncateContent(cf.getContent())); - } - } else { - // remove config info - configInfoPersistService.removeConfigInfo(dataId, group, tenant, InetUtils.getSelfIP(), null); - LOGGER.warn("[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" - + group); - } - - } catch (Throwable e) { - LOGGER.info("[merge-error] " + dataId + ", " + group + ", " + e.toString(), e); - } - FINISHED.incrementAndGet(); - if (FINISHED.get() % 100 == 0) { - LOGGER.info("[all-merge-dump] {} / {}", FINISHED.get(), total); - } - } - LOGGER.info("[all-merge-dump] {} / {}", FINISHED.get(), total); - } - - public void executeConfigsMerge(List configInfoList) { - new MergeAllDataWorker(configInfoList).start(); - } - - public class MergeAllDataWorker extends Thread { - - static final int PAGE_SIZE = 10000; - - private List configInfoList; - - public MergeAllDataWorker(List configInfoList) { - super("MergeAllDataWorker"); - this.configInfoList = configInfoList; - } - - @Override - public void run() { - executeMergeConfigTask(configInfoList, PAGE_SIZE); - } - } -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessor.java deleted file mode 100755 index 89745589fdc..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessor.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.merge; - -import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.task.NacosTask; -import com.alibaba.nacos.config.server.constant.Constants; -import com.alibaba.nacos.common.task.NacosTaskProcessor; -import com.alibaba.nacos.config.server.model.ConfigInfo; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; -import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; -import com.alibaba.nacos.config.server.utils.ContentUtils; -import com.alibaba.nacos.config.server.utils.TimeUtils; -import com.alibaba.nacos.sys.utils.InetUtils; -import com.alibaba.nacos.common.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; - -/** - * Merge task processor. - * - * @author Nacos - */ -public class MergeTaskProcessor implements NacosTaskProcessor { - - private static final Logger LOGGER = LoggerFactory.getLogger(MergeTaskProcessor.class); - - private static final int PAGE_SIZE = 10000; - - private ConfigInfoPersistService configInfoPersistService; - - private ConfigInfoAggrPersistService configInfoAggrPersistService; - - private ConfigInfoTagPersistService configInfoTagPersistService; - - private MergeDatumService mergeService; - - MergeTaskProcessor(ConfigInfoPersistService configInfoPersistService, - ConfigInfoAggrPersistService configInfoAggrPersistService, - ConfigInfoTagPersistService configInfoTagPersistService, MergeDatumService mergeService) { - this.configInfoPersistService = configInfoPersistService; - this.configInfoAggrPersistService = configInfoAggrPersistService; - this.configInfoTagPersistService = configInfoTagPersistService; - this.mergeService = mergeService; - } - - @Override - public boolean process(NacosTask task) { - MergeDataTask mergeTask = (MergeDataTask) task; - final String dataId = mergeTask.dataId; - final String group = mergeTask.groupId; - final String tenant = mergeTask.tenant; - final String tag = mergeTask.tag; - final String clientIp = mergeTask.getClientIp(); - try { - List datumList = new ArrayList<>(); - int rowCount = configInfoAggrPersistService.aggrConfigInfoCount(dataId, group, tenant); - int pageCount = (int) Math.ceil(rowCount * 1.0 / PAGE_SIZE); - for (int pageNo = 1; pageNo <= pageCount; pageNo++) { - Page page = configInfoAggrPersistService.findConfigInfoAggrByPage(dataId, group, tenant, - pageNo, PAGE_SIZE); - if (page != null) { - datumList.addAll(page.getPageItems()); - LOGGER.info("[merge-query] {}, {}, size/total={}/{}", dataId, group, datumList.size(), rowCount); - } - } - - final Timestamp time = TimeUtils.getCurrentTime(); - if (datumList.size() > 0) { - // merge - ConfigInfo cf = merge(dataId, group, tenant, datumList); - - configInfoPersistService.insertOrUpdate(null, null, cf, null); - - LOGGER.info("[merge-ok] {}, {}, size={}, length={}, md5={}, content={}", dataId, group, - datumList.size(), cf.getContent().length(), cf.getMd5(), - ContentUtils.truncateContent(cf.getContent())); - - ConfigTraceService.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), - InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT, - ConfigTraceService.PERSISTENCE_TYPE_MERGE, cf.getContent()); - } else { - String eventType; - - // remove - if (StringUtils.isBlank(tag)) { - eventType = ConfigTraceService.PERSISTENCE_EVENT; - - configInfoPersistService.removeConfigInfo(dataId, group, tenant, clientIp, null); - } else { - eventType = ConfigTraceService.PERSISTENCE_EVENT_TAG + "-" + tag; - - configInfoTagPersistService.removeConfigInfoTag(dataId, group, tenant, tag, clientIp, null); - } - - LOGGER.warn( - "[merge-delete] delete config info because no datum. dataId=" + dataId + ", groupId=" + group); - - ConfigTraceService.logPersistenceEvent(dataId, group, tenant, null, time.getTime(), - InetUtils.getSelfIP(), eventType, ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null); - } - NotifyCenter.publishEvent(new ConfigDataChangeEvent(false, dataId, group, tenant, tag, time.getTime())); - - } catch (Exception e) { - mergeService.addMergeTask(dataId, group, tenant, mergeTask.getClientIp()); - LOGGER.info("[merge-error] " + dataId + ", " + group + ", " + e.toString(), e); - } - - return true; - } - - /** - * merge datumList {@link ConfigInfoAggr}. - * - * @param dataId data id - * @param group group - * @param tenant tenant - * @param datumList datumList - * @return {@link ConfigInfo} - */ - public static ConfigInfo merge(String dataId, String group, String tenant, List datumList) { - StringBuilder sb = new StringBuilder(); - String appName = null; - for (ConfigInfoAggr aggrInfo : datumList) { - if (aggrInfo.getAppName() != null) { - appName = aggrInfo.getAppName(); - } - sb.append(aggrInfo.getContent()); - sb.append(Constants.NACOS_LINE_SEPARATOR); - } - String content = sb.substring(0, sb.lastIndexOf(Constants.NACOS_LINE_SEPARATOR)); - return new ConfigInfo(dataId, group, tenant, appName, content); - } -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyService.java index cb66c8f4d22..ce9abebc0a9 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyService.java @@ -25,11 +25,14 @@ import com.alibaba.nacos.common.task.AbstractDelayTask; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.monitor.MetricsMonitor; import com.alibaba.nacos.config.server.remote.ConfigClusterRpcClientProxy; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import com.alibaba.nacos.config.server.utils.ConfigExecutor; import com.alibaba.nacos.config.server.utils.LogUtil; +import com.alibaba.nacos.config.server.utils.PropertyUtil; import com.alibaba.nacos.core.cluster.Member; import com.alibaba.nacos.core.cluster.NodeState; import com.alibaba.nacos.core.cluster.ServerMemberManager; @@ -47,6 +50,8 @@ import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import static com.alibaba.nacos.core.cluster.MemberMetaDataConstants.SUPPORT_GRAY_MODEL; + /** * Async notify service. * @@ -101,12 +106,8 @@ public Class subscribeType() { void handleConfigDataChangeEvent(Event event) { if (event instanceof ConfigDataChangeEvent) { ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event; - long dumpTs = evt.lastModifiedTs; - String dataId = evt.dataId; - String group = evt.group; - String tenant = evt.tenant; - String tag = evt.tag; - MetricsMonitor.incrementConfigChangeCount(tenant, group, dataId); + + MetricsMonitor.incrementConfigChangeCount(evt.tenant, evt.group, evt.dataId); Collection ipList = memberManager.allMembersWithoutSelf(); @@ -115,8 +116,11 @@ void handleConfigDataChangeEvent(Event event) { for (Member member : ipList) { // grpc report data change only - rpcQueue.add( - new NotifySingleRpcTask(dataId, group, tenant, tag, dumpTs, evt.isBeta, evt.isBatch, member)); + NotifySingleRpcTask notifySingleRpcTask = generateTask(evt, member); + if (notifySingleRpcTask != null) { + rpcQueue.add(notifySingleRpcTask); + } + } if (!rpcQueue.isEmpty()) { ConfigExecutor.executeAsyncNotify(new AsyncRpcTask(rpcQueue)); @@ -124,6 +128,30 @@ void handleConfigDataChangeEvent(Event event) { } } + private NotifySingleRpcTask generateTask(ConfigDataChangeEvent configDataChangeEvent, Member member) { + + NotifySingleRpcTask task = new NotifySingleRpcTask(configDataChangeEvent.dataId, configDataChangeEvent.group, + configDataChangeEvent.tenant, configDataChangeEvent.grayName, configDataChangeEvent.lastModifiedTs, + member); + + if (PropertyUtil.isGrayCompatibleModel() && StringUtils.isNotBlank(configDataChangeEvent.grayName)) { + + // old server should set beta or tag flag + if (!(Boolean) member.getExtendInfo().getOrDefault(SUPPORT_GRAY_MODEL, Boolean.FALSE)) { + String underLine = "_"; + task.setBeta(BetaGrayRule.TYPE_BETA.equals(configDataChangeEvent.grayName)); + if (configDataChangeEvent.grayName.startsWith(TagGrayRule.TYPE_TAG + underLine)) { + task.setTag(configDataChangeEvent.grayName.substring( + configDataChangeEvent.grayName.indexOf(TagGrayRule.TYPE_TAG + underLine) + 4)); + } + + } + } + + // compatible with gray model + return task; + } + private boolean isUnHealthy(String targetIp) { return !memberManager.stateCheck(targetIp, HEALTHY_CHECK_STATUS); } @@ -134,12 +162,12 @@ void executeAsyncRpcTask(Queue queue) { ConfigChangeClusterSyncRequest syncRequest = new ConfigChangeClusterSyncRequest(); syncRequest.setDataId(task.getDataId()); + syncRequest.setTenant(task.getTenant()); syncRequest.setGroup(task.getGroup()); - syncRequest.setBeta(task.isBeta()); syncRequest.setLastModified(task.getLastModified()); + syncRequest.setGrayName(task.getGrayName()); + syncRequest.setBeta(task.isBeta()); syncRequest.setTag(task.getTag()); - syncRequest.setBatch(task.isBatch()); - syncRequest.setTenant(task.getTenant()); Member member = task.member; String event = getNotifyEvent(task); @@ -200,27 +228,24 @@ public static class NotifySingleRpcTask extends AbstractDelayTask { private Member member; + private String grayName; + + @Deprecated private boolean isBeta; + @Deprecated private String tag; - private boolean isBatch; - - public NotifySingleRpcTask(String dataId, String group, String tenant, String tag, long lastModified, - boolean isBeta, boolean isBatch, Member member) { - this(dataId, group, tenant, lastModified); - this.member = member; - this.isBeta = isBeta; - this.tag = tag; - this.isBatch = isBatch; - } - - private NotifySingleRpcTask(String dataId, String group, String tenant, long lastModified) { + public NotifySingleRpcTask(String dataId, String group, String tenant, String grayName, long lastModified, + Member member) { this.dataId = dataId; this.group = group; this.tenant = tenant; this.lastModified = lastModified; + this.member = member; + this.grayName = grayName; setTaskInterval(3000L); + } public boolean isBeta() { @@ -239,12 +264,12 @@ public void setTag(String tag) { this.tag = tag; } - public boolean isBatch() { - return isBatch; + public String getGrayName() { + return grayName; } - public void setBatch(boolean batch) { - isBatch = batch; + public void setGrayName(String grayName) { + this.grayName = grayName; } public String getDataId() { @@ -293,8 +318,8 @@ private static String getNotifyEvent(NotifySingleRpcTask task) { event = ConfigTraceService.NOTIFY_EVENT_BETA; } else if (!StringUtils.isBlank(task.tag)) { event = ConfigTraceService.NOTIFY_EVENT_TAG + "-" + task.tag; - } else if (task.isBatch()) { - event = ConfigTraceService.NOTIFY_EVENT_BATCH; + } else if (StringUtils.isNotBlank(task.grayName)) { + event = ConfigTraceService.NOTIFY_EVENT + "-" + task.grayName; } return event; } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoAggrPersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoAggrPersistService.java deleted file mode 100644 index 6a1df0859ea..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoAggrPersistService.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.repository; - -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.persistence.repository.PaginationHelper; - -import java.util.List; -import java.util.Map; - -/** - * Database service, providing access to config_info_aggr in the database. - * - * @author lixiaoshuang - */ -public interface ConfigInfoAggrPersistService { - - Object[] EMPTY_ARRAY = new Object[] {}; - - String PATTERN_STR = "*"; - - /** - * create Pagination utils. - * - * @param Generic object - * @return {@link PaginationHelper} - */ - PaginationHelper createPaginationHelper(); - - //------------------------------------------insert---------------------------------------------// - - /** - * Add data before aggregation to the database, select -> update or insert . - * - * @param dataId data id - * @param group group - * @param tenant tenant - * @param datumId datum id - * @param appName app name - * @param content config content - * @return {@code true} if add success - */ - boolean addAggrConfigInfo(final String dataId, final String group, String tenant, final String datumId, - String appName, final String content); - - /** - * Add or update data in batches. Any exception during the transaction will force a TransactionSystemException to be - * thrown. - * - * @param dataId dataId - * @param group group - * @param tenant tenant - * @param appName app name - * @param datumMap datumMap - * @return {@code true} if publish success - */ - boolean batchPublishAggr(final String dataId, final String group, final String tenant, - final Map datumMap, final String appName); - - - //------------------------------------------select---------------------------------------------// - - /** - * Get count of aggregation config info. - * - * @param dataId data id - * @param group group - * @param tenant tenant - * @return count - */ - int aggrConfigInfoCount(String dataId, String group, String tenant); - - /** - * Query aggregation config info. - * - * @param dataId data id - * @param group group - * @param tenant tenant - * @param pageNo page number - * @param pageSize page size - * @return {@link Page} with {@link ConfigInfoAggr} generation - */ - Page findConfigInfoAggrByPage(String dataId, String group, String tenant, final int pageNo, - final int pageSize); - - /** - * Find all aggregated data sets. - * - * @return {@link ConfigInfoChanged} list - */ - List findAllAggrGroup(); - -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoBetaPersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoBetaPersistService.java index 69d5cd9c892..f98b43a6065 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoBetaPersistService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoBetaPersistService.java @@ -27,9 +27,10 @@ /** * Database service, providing access to config_info_beta in the database. - * + * Deprecated since 2.5.0,only support on compatibility,replaced with ConfigInfoGray model, will be soon removed on further version. * @author lixiaoshuang */ +@Deprecated public interface ConfigInfoBetaPersistService { /** diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoGrayPersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoGrayPersistService.java new file mode 100644 index 00000000000..791b620d3b5 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoGrayPersistService.java @@ -0,0 +1,201 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.repository; + +import com.alibaba.nacos.config.server.model.ConfigInfo; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; +import com.alibaba.nacos.config.server.model.ConfigOperateResult; +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.persistence.repository.PaginationHelper; + +import java.sql.Timestamp; +import java.util.List; + +/** + * Database service, providing access to config_info_gray in the database. + * + * @author rong + */ +public interface ConfigInfoGrayPersistService { + + /** + * create Pagination utils. + * + * @param Generic object + * @return {@link PaginationHelper} + */ + PaginationHelper createPaginationHelper(); + + //------------------------------------------insert---------------------------------------------// + + + /** + * get gray config info state. + * + * @param dataId dataId. + * @param group group. + * @param tenant tenant. + * @param grayName gray name. + * @return config info state. + */ + ConfigInfoStateWrapper findConfigInfo4GrayState(final String dataId, final String group, final String tenant, + String grayName); + + /** + * Add gray configuration information and publish data change events. + * + * @param configInfo config info + * @param grayName gray name + * @param grayRule gray rule + * @param srcIp remote ip + * @param srcUser user + * @return config operation result. + */ + ConfigOperateResult addConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser); + + /** + * Adds configuration information with database atomic operations, minimizing SQL actions and avoiding business + * encapsulation. + * + * @param configGrayId the ID for the gray configuration + * @param configInfo the configuration information to be added + * @param grayName the name of the gray configuration + * @param grayRule the rule of the gray configuration + * @param srcIp the IP address of the source + * @param srcUser the user who performs the addition + */ + void addConfigInfoGrayAtomic(final long configGrayId, final ConfigInfo configInfo, final String grayName, final String grayRule, + final String srcIp, final String srcUser); + + /** + * insert or update gray config. + * + * @param configInfo config info + * @param grayName gray name + * @param grayRule gray rule + * @param srcIp remote ip + * @param srcUser user + * @return config operation result. + */ + ConfigOperateResult insertOrUpdateGray(final ConfigInfo configInfo, final String grayName, final String grayRule, + final String srcIp, final String srcUser); + + /** + * insert or update gray config cas. + * + * @param configInfo config info. + * @param grayName gray name + * @param grayRule gray rule + * @param srcIp remote ip. + * @param srcUser user. + * @return config operation result. + */ + ConfigOperateResult insertOrUpdateGrayCas(final ConfigInfo configInfo, final String grayName, final String grayRule, + final String srcIp, final String srcUser); + //------------------------------------------delete---------------------------------------------// + + /** + * Delete configuration; database atomic operation, minimum SQL action, no business encapsulation. + * + * @param dataId dataId + * @param group group + * @param tenant tenant + * @param grayName gray name + * @param srcIp remote ip + * @param srcUser user + */ + void removeConfigInfoGray(final String dataId, final String group, final String tenant, final String grayName, + final String srcIp, final String srcUser); + //------------------------------------------update---------------------------------------------// + + /** + * Update gray configuration information. + * + * @param configInfo config info + * @param grayName gray name + * @param grayRule gray rule + * @param srcIp remote ip + * @param srcUser user + * @return config operation result. + */ + ConfigOperateResult updateConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser); + + /** + * Update gray configuration information. + * + * @param configInfo config info + * @param grayName gray name + * @param grayRule gray rule + * @param srcIp remote ip + * @param srcUser user + * @return success or not. + */ + ConfigOperateResult updateConfigInfo4GrayCas(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser); + //------------------------------------------select---------------------------------------------// + + /** + * Query gray configuration information based on dataId and group. + * + * @param dataId data id + * @param group group + * @param tenant tenant + * @param grayName gray name + * @return ConfigInfoGrayWrapper gray model instance. + */ + ConfigInfoGrayWrapper findConfigInfo4Gray(final String dataId, final String group, final String tenant, + final String grayName); + + /** + * Returns the number of gray configuration items. + * + * @return number of configuration items. + */ + int configInfoGrayCount(); + + /** + * Query all gray config info for dump task. + * + * @param pageNo page numbser + * @param pageSize page sizxe + * @return {@link Page} with {@link ConfigInfoGrayWrapper} generation + */ + Page findAllConfigInfoGrayForDumpAll(final int pageNo, final int pageSize); + + /** + * Query all gray config info for dump task. + * + * @param startTime startTime + * @param lastMaxId lastMaxId + * @param pageSize pageSize + * @return {@link Page} with {@link ConfigInfoGrayWrapper} generation + */ + List findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize); + + /** + * found all config grays. + * + * @param dataId dataId. + * @param group group. + * @param tenant tenant. + * @return + */ + List findConfigInfoGrays(final String dataId, final String group, final String tenant); +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoPersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoPersistService.java index afb006529e0..d182900fa2a 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoPersistService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoPersistService.java @@ -169,10 +169,10 @@ void removeConfigInfo(final String dataId, final String group, final String tena * @param ids id list * @param srcIp remote ip * @param srcUser user - * @return {@link ConfigInfo} list + * @return {@link ConfigAllInfo} list * @author klw */ - List removeConfigInfoByIds(final List ids, final String srcIp, final String srcUser); + List removeConfigInfoByIds(final List ids, final String srcIp, final String srcUser); /** * Delete tag. diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoTagPersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoTagPersistService.java index 06306b22662..a864977b2b8 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoTagPersistService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoTagPersistService.java @@ -29,9 +29,10 @@ /** * Database service, providing access to config_info_tag in the database. - * + * Deprecated since 2.5.0,only support on compatibility,replaced with ConfigInfoGray model, will be soon removed on further version. * @author lixiaoshuang */ +@Deprecated public interface ConfigInfoTagPersistService { /** diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector.java index 8b45b37905e..927d84a1a12 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector.java @@ -22,10 +22,10 @@ import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.ConfigInfo4Beta; import com.alibaba.nacos.config.server.model.ConfigInfo4Tag; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; import com.alibaba.nacos.config.server.model.ConfigInfoBase; import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoChanged; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoWrapper; @@ -55,6 +55,8 @@ public class ConfigRowMapperInjector { public static final ConfigInfoTagWrapperRowMapper CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER = new ConfigInfoTagWrapperRowMapper(); + public static final ConfigInfoGrayWrapperRowMapper CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER = new ConfigInfoGrayWrapperRowMapper(); + public static final ConfigInfoRowMapper CONFIG_INFO_ROW_MAPPER = new ConfigInfoRowMapper(); public static final ConfigAdvanceInfoRowMapper CONFIG_ADVANCE_INFO_ROW_MAPPER = new ConfigAdvanceInfoRowMapper(); @@ -67,8 +69,6 @@ public class ConfigRowMapperInjector { public static final ConfigInfoBaseRowMapper CONFIG_INFO_BASE_ROW_MAPPER = new ConfigInfoBaseRowMapper(); - public static final ConfigInfoAggrRowMapper CONFIG_INFO_AGGR_ROW_MAPPER = new ConfigInfoAggrRowMapper(); - public static final ConfigInfoChangedRowMapper CONFIG_INFO_CHANGED_ROW_MAPPER = new ConfigInfoChangedRowMapper(); public static final ConfigHistoryRowMapper HISTORY_LIST_ROW_MAPPER = new ConfigHistoryRowMapper(); @@ -146,12 +146,6 @@ private static void injectConfigRowMapper() { ConfigRowMapperInjector.CONFIG_INFO_BASE_ROW_MAPPER.getClass().getCanonicalName(), ConfigRowMapperInjector.CONFIG_INFO_BASE_ROW_MAPPER); - // CONFIG_INFO_AGGR_ROW_MAPPER - - RowMapperManager.registerRowMapper( - ConfigRowMapperInjector.CONFIG_INFO_AGGR_ROW_MAPPER.getClass().getCanonicalName(), - ConfigRowMapperInjector.CONFIG_INFO_AGGR_ROW_MAPPER); - // CONFIG_INFO_CHANGED_ROW_MAPPER RowMapperManager.registerRowMapper( @@ -181,7 +175,7 @@ public ConfigInfoWrapper mapRow(ResultSet rs, int rowNum) throws SQLException { info.setGroup(rs.getString("group_id")); info.setTenant(rs.getString("tenant_id")); info.setAppName(rs.getString("app_name")); - + try { info.setType(rs.getString("type")); } catch (SQLException ignore) { @@ -305,6 +299,48 @@ public ConfigInfoTagWrapper mapRow(ResultSet rs, int rowNum) throws SQLException } } + public static final class ConfigInfoGrayWrapperRowMapper implements RowMapper { + + @Override + public ConfigInfoGrayWrapper mapRow(ResultSet rs, int rowNum) throws SQLException { + ConfigInfoGrayWrapper info = new ConfigInfoGrayWrapper(); + + info.setDataId(rs.getString("data_id")); + info.setGroup(rs.getString("group_id")); + info.setTenant(rs.getString("tenant_id")); + info.setGrayName(rs.getString("gray_name")); + info.setGrayRule(rs.getString("gray_rule")); + info.setAppName(rs.getString("app_name")); + + try { + info.setContent(rs.getString("content")); + } catch (SQLException ignore) { + } + try { + info.setId(rs.getLong("id")); + } catch (SQLException ignore) { + } + try { + info.setLastModified(rs.getTimestamp("gmt_modified").getTime()); + } catch (SQLException ignore) { + } + try { + info.setMd5(rs.getString("md5")); + } catch (SQLException ignore) { + } + try { + info.setEncryptedDataKey(rs.getString("encrypted_data_key")); + } catch (SQLException ignore) { + } + + try { + info.setSrcUser(rs.getString("src_user")); + } catch (SQLException ignore) { + } + return info; + } + } + public static final class ConfigInfoRowMapper implements RowMapper { @Override @@ -488,21 +524,6 @@ public ConfigInfoBase mapRow(ResultSet rs, int rowNum) throws SQLException { } } - public static final class ConfigInfoAggrRowMapper implements RowMapper { - - @Override - public ConfigInfoAggr mapRow(ResultSet rs, int rowNum) throws SQLException { - ConfigInfoAggr info = new ConfigInfoAggr(); - info.setDataId(rs.getString("data_id")); - info.setGroup(rs.getString("group_id")); - info.setDatumId(rs.getString("datum_id")); - info.setTenant(rs.getString("tenant_id")); - info.setAppName(rs.getString("app_name")); - info.setContent(rs.getString("content")); - return info; - } - } - public static final class ConfigInfoChangedRowMapper implements RowMapper { @Override @@ -528,6 +549,8 @@ public ConfigHistoryInfo mapRow(ResultSet rs, int rowNum) throws SQLException { configHistoryInfo.setSrcIp(rs.getString("src_ip")); configHistoryInfo.setSrcUser(rs.getString("src_user")); configHistoryInfo.setOpType(rs.getString("op_type")); + configHistoryInfo.setPublishType(rs.getString("publish_type")); + configHistoryInfo.setExtInfo(rs.getString("ext_info")); configHistoryInfo.setCreatedTime(rs.getTimestamp("gmt_create")); configHistoryInfo.setLastModifiedTime(rs.getTimestamp("gmt_modified")); return configHistoryInfo; @@ -549,6 +572,8 @@ public ConfigHistoryInfo mapRow(ResultSet rs, int rowNum) throws SQLException { configHistoryInfo.setSrcUser(rs.getString("src_user")); configHistoryInfo.setSrcIp(rs.getString("src_ip")); configHistoryInfo.setOpType(rs.getString("op_type")); + configHistoryInfo.setPublishType(rs.getString("publish_type")); + configHistoryInfo.setExtInfo(rs.getString("ext_info")); configHistoryInfo.setCreatedTime(rs.getTimestamp("gmt_create")); configHistoryInfo.setLastModifiedTime(rs.getTimestamp("gmt_modified")); try { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/HistoryConfigInfoPersistService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/HistoryConfigInfoPersistService.java index e0e14b71568..3b64db45064 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/HistoryConfigInfoPersistService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/HistoryConfigInfoPersistService.java @@ -45,15 +45,17 @@ public interface HistoryConfigInfoPersistService { /** * Update change records; database atomic operations, minimal sql actions, no business encapsulation. * - * @param id id - * @param configInfo config info - * @param srcIp ip - * @param srcUser user - * @param time time - * @param ops ops type + * @param id id + * @param configInfo config info + * @param srcIp ip + * @param srcUser user + * @param time time + * @param ops ops type + * @param publishType publish type + * @param extInfo extra config info */ void insertConfigHistoryAtomic(long id, ConfigInfo configInfo, String srcIp, String srcUser, final Timestamp time, - String ops); + String ops, String publishType, String extInfo); //------------------------------------------delete---------------------------------------------// /** @@ -69,12 +71,13 @@ void insertConfigHistoryAtomic(long id, ConfigInfo configInfo, String srcIp, Str /** * Query deleted config. * - * @param startTime start time - * @param startId last max id - * @param size page size + * @param startTime start time + * @param startId last max id + * @param size page size + * @param publishType publish type * @return {@link ConfigInfoStateWrapper} list */ - List findDeletedConfig(final Timestamp startTime, final long startId, int size); + List findDeletedConfig(final Timestamp startTime, final long startId, int size, String publishType); /** * List configuration history change record. diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImpl.java deleted file mode 100644 index dab8c013af8..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImpl.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.repository.embedded; - -import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.exception.NacosConfigException; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage; -import com.alibaba.nacos.persistence.datasource.DataSourceService; -import com.alibaba.nacos.persistence.datasource.DynamicDataSource; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.persistence.model.event.DerbyImportEvent; -import com.alibaba.nacos.persistence.repository.PaginationHelper; -import com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl; -import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; -import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate; -import com.alibaba.nacos.plugin.datasource.MapperManager; -import com.alibaba.nacos.plugin.datasource.constants.CommonConstant; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.constants.TableConstant; -import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoAggrMapper; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; -import com.alibaba.nacos.sys.env.EnvUtil; -import org.springframework.context.annotation.Conditional; -import org.springframework.stereotype.Service; - -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_AGGR_ROW_MAPPER; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_CHANGED_ROW_MAPPER; - -/** - * EmbeddedConfigInfoAggrPersistServiceImpl. - * - * @author lixiaoshuang - */ -@SuppressWarnings({"PMD.MethodReturnWrapperTypeRule", "checkstyle:linelength"}) -@Conditional(value = ConditionOnEmbeddedStorage.class) -@Service("embeddedConfigInfoAggrPersistServiceImpl") -public class EmbeddedConfigInfoAggrPersistServiceImpl implements ConfigInfoAggrPersistService { - - private DataSourceService dataSourceService; - - private final DatabaseOperate databaseOperate; - - private MapperManager mapperManager; - - /** - * The constructor sets the dependency injection order. - * - * @param databaseOperate databaseOperate. - */ - public EmbeddedConfigInfoAggrPersistServiceImpl(DatabaseOperate databaseOperate) { - this.databaseOperate = databaseOperate; - this.dataSourceService = DynamicDataSource.getInstance().getDataSource(); - Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class, - false); - this.mapperManager = MapperManager.instance(isDataSourceLogEnable); - NotifyCenter.registerToSharePublisher(DerbyImportEvent.class); - } - - @Override - public PaginationHelper createPaginationHelper() { - return new EmbeddedPaginationHelperImpl<>(databaseOperate); - } - - @Override - public boolean addAggrConfigInfo(final String dataId, final String group, String tenant, final String datumId, - String appName, final String content) { - String appNameTmp = StringUtils.isBlank(appName) ? StringUtils.EMPTY : appName; - String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; - String contentTmp = StringUtils.isBlank(content) ? StringUtils.EMPTY : content; - final Timestamp now = new Timestamp(System.currentTimeMillis()); - - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - final String select = configInfoAggrMapper.select(Collections.singletonList("content"), - Arrays.asList("data_id", "group_id", "tenant_id", "datum_id")); - final String insert = configInfoAggrMapper.insert( - Arrays.asList("data_id", "group_id", "tenant_id", "datum_id", "app_name", "content", "gmt_modified")); - final String update = configInfoAggrMapper.update(Arrays.asList("content", "gmt_modified"), - Arrays.asList("data_id", "group_id", "tenant_id", "datum_id")); - - String dbContent = databaseOperate.queryOne(select, new Object[] {dataId, group, tenantTmp, datumId}, - String.class); - - if (Objects.isNull(dbContent)) { - final Object[] args = new Object[] {dataId, group, tenantTmp, datumId, appNameTmp, contentTmp, now}; - EmbeddedStorageContextHolder.addSqlContext(insert, args); - } else if (!dbContent.equals(content)) { - final Object[] args = new Object[] {contentTmp, now, dataId, group, tenantTmp, datumId}; - EmbeddedStorageContextHolder.addSqlContext(update, args); - } - - try { - boolean result = databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext()); - if (!result) { - throw new NacosConfigException("[Merge] Configuration release failed"); - } - return true; - } finally { - EmbeddedStorageContextHolder.cleanAllContext(); - } - } - - @Override - public boolean batchPublishAggr(final String dataId, final String group, final String tenant, - final Map datumMap, final String appName) { - try { - Boolean isPublishOk = false; - for (Map.Entry entry : datumMap.entrySet()) { - addAggrConfigInfo(dataId, group, tenant, entry.getKey(), appName, entry.getValue()); - } - - isPublishOk = databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext()); - - if (isPublishOk == null) { - return false; - } - return isPublishOk; - } finally { - EmbeddedStorageContextHolder.cleanAllContext(); - } - } - - @Override - public int aggrConfigInfoCount(String dataId, String group, String tenant) { - String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - String sql = configInfoAggrMapper.count(Arrays.asList("data_id", "group_id", "tenant_id")); - Integer result = databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp}, Integer.class); - if (result == null) { - throw new IllegalArgumentException("aggrConfigInfoCount error"); - } - return result; - } - - @Override - public Page findConfigInfoAggrByPage(String dataId, String group, String tenant, final int pageNo, - final int pageSize) { - String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - final int startRow = (pageNo - 1) * pageSize; - final String sqlCountRows = configInfoAggrMapper.select(Collections.singletonList("count(*)"), - Arrays.asList("data_id", "group_id", "tenant_id")); - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, group); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp); - context.setStartRow(startRow); - context.setPageSize(pageSize); - MapperResult mapperResult = configInfoAggrMapper.findConfigInfoAggrByPageFetchRows(context); - String sqlFetchRows = mapperResult.getSql(); - Object[] sqlFetchArgs = mapperResult.getParamList().toArray(); - - PaginationHelper helper = createPaginationHelper(); - return helper.fetchPageLimit(sqlCountRows, new Object[] {dataId, group, tenantTmp}, sqlFetchRows, sqlFetchArgs, - pageNo, pageSize, CONFIG_INFO_AGGR_ROW_MAPPER); - } - - @Override - public List findAllAggrGroup() { - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - MapperResult mapperResult = configInfoAggrMapper.findAllAggrGroupByDistinct(null); - - return databaseOperate.queryMany(mapperResult.getSql(), EMPTY_ARRAY, CONFIG_INFO_CHANGED_ROW_MAPPER); - - } - -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImpl.java new file mode 100644 index 00000000000..f5f9e378d6b --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImpl.java @@ -0,0 +1,426 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.repository.embedded; + +import com.alibaba.nacos.common.notify.NotifyCenter; +import com.alibaba.nacos.common.utils.MD5Utils; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.config.server.constant.Constants; +import com.alibaba.nacos.config.server.model.ConfigInfo; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; +import com.alibaba.nacos.config.server.model.ConfigOperateResult; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; +import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; +import com.alibaba.nacos.config.server.utils.LogUtil; +import com.alibaba.nacos.core.distributed.id.IdGeneratorManager; +import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage; +import com.alibaba.nacos.persistence.datasource.DataSourceService; +import com.alibaba.nacos.persistence.datasource.DynamicDataSource; +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.persistence.model.event.DerbyImportEvent; +import com.alibaba.nacos.persistence.repository.PaginationHelper; +import com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl; +import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; +import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate; +import com.alibaba.nacos.plugin.datasource.MapperManager; +import com.alibaba.nacos.plugin.datasource.constants.CommonConstant; +import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; +import com.alibaba.nacos.plugin.datasource.constants.TableConstant; +import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper; +import com.alibaba.nacos.plugin.datasource.model.MapperContext; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Conditional; +import org.springframework.dao.DataAccessException; +import org.springframework.stereotype.Service; + +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER; +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; + +/** + * EmbeddedConfigInfoGrayPersistServiceImpl. + * + * @author rong + */ +@SuppressWarnings({"PMD.MethodReturnWrapperTypeRule", "checkstyle:linelength"}) +@Conditional(value = ConditionOnEmbeddedStorage.class) +@Service("embeddedConfigInfoGrayPersistServiceImpl") +public class EmbeddedConfigInfoGrayPersistServiceImpl implements ConfigInfoGrayPersistService { + + private static final String RESOURCE_CONFIG_HISTORY_ID = "config-history-id"; + + private static final String RESOURCE_CONFIG_HISTORY_GRAY_ID = "config-history-gray-id"; + + private DataSourceService dataSourceService; + + private final DatabaseOperate databaseOperate; + + private MapperManager mapperManager; + + private final IdGeneratorManager idGeneratorManager; + + private final HistoryConfigInfoPersistService historyConfigInfoPersistService; + + /** + * The constructor sets the dependency injection order. + * + * @param databaseOperate databaseOperate. + */ + public EmbeddedConfigInfoGrayPersistServiceImpl(DatabaseOperate databaseOperate, + IdGeneratorManager idGeneratorManager, + @Qualifier("embeddedHistoryConfigInfoPersistServiceImpl") HistoryConfigInfoPersistService historyConfigInfoPersistService) { + this.databaseOperate = databaseOperate; + this.idGeneratorManager = idGeneratorManager; + this.historyConfigInfoPersistService = historyConfigInfoPersistService; + idGeneratorManager.register(RESOURCE_CONFIG_HISTORY_GRAY_ID, RESOURCE_CONFIG_HISTORY_ID); + this.dataSourceService = DynamicDataSource.getInstance().getDataSource(); + Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class, + false); + this.mapperManager = MapperManager.instance(isDataSourceLogEnable); + NotifyCenter.registerToSharePublisher(DerbyImportEvent.class); + } + + @Override + public PaginationHelper createPaginationHelper() { + return new EmbeddedPaginationHelperImpl<>(databaseOperate); + } + + @Override + public ConfigInfoStateWrapper findConfigInfo4GrayState(final String dataId, final String group, final String tenant, + String grayName) { + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + + String sql = configInfoGrayMapper.select( + Arrays.asList("id", "data_id", "group_id", "tenant_id", "gmt_modified"), + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")); + return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp, grayNameTmp}, + CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER); + } + + private ConfigOperateResult getGrayOperateResult(String dataId, String group, String tenant, String grayName) { + String tenantTmp = StringUtils.defaultEmptyIfBlank(tenant); + ConfigInfoStateWrapper configInfo4Gray = this.findConfigInfo4GrayState(dataId, group, tenantTmp, grayName); + if (configInfo4Gray == null) { + return new ConfigOperateResult(false); + } + return new ConfigOperateResult(configInfo4Gray.getId(), configInfo4Gray.getLastModified()); + + } + + @Override + public ConfigOperateResult addConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, String srcIp, + String srcUser) { + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + + configInfo.setTenant(tenantTmp); + + try { + long configGrayId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_GRAY_ID); + long hisId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_ID); + + addConfigInfoGrayAtomic(configGrayId, configInfo, grayNameTmp, grayRuleTmp, srcIp, srcUser); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, now, "I", + Constants.GRAY, ConfigExtInfoUtil.getExtInfoFromGrayInfo(grayNameTmp, grayRuleTmp, srcUser)); + + EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, now); + databaseOperate.blockUpdate(); + + return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + } finally { + EmbeddedStorageContextHolder.cleanAllContext(); + } + } + + @Override + public void addConfigInfoGrayAtomic(long configGrayId, ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser) { + String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + + final String sql = configInfoGrayMapper.insert( + Arrays.asList("id", "data_id", "group_id", "tenant_id", "gray_name", "gray_rule", "app_name", "content", + "md5", "src_ip", "src_user", "gmt_create", "gmt_modified")); + + Timestamp time = new Timestamp(System.currentTimeMillis()); + final Object[] args = new Object[] {configGrayId, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, + grayNameTmp, grayRuleTmp, appNameTmp, configInfo.getContent(), md5, srcIp, srcUser, time, time}; + EmbeddedStorageContextHolder.addSqlContext(sql, args); + } + + @Override + public ConfigOperateResult insertOrUpdateGray(final ConfigInfo configInfo, final String grayName, + final String grayRule, final String srcIp, final String srcUser) { + if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName) + == null) { + return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser); + } else { + return updateConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser); + } + } + + @Override + public ConfigOperateResult insertOrUpdateGrayCas(final ConfigInfo configInfo, final String grayName, + final String grayRule, final String srcIp, final String srcUser) { + if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName) + == null) { + return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser); + } else { + return updateConfigInfo4GrayCas(configInfo, grayName, grayRule, srcIp, srcUser); + } + } + + @Override + public void removeConfigInfoGray(final String dataId, final String group, final String tenant, + final String grayName, final String srcIp, final String srcUser) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName; + + ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(dataId, group, tenantTmp, grayNameTmp); + if (oldConfigAllInfo4Gray == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", dataId, + group, tenant); + } + } + + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + final String sql = configInfoGrayMapper.delete(Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")); + final Object[] args = new Object[] {dataId, group, tenantTmp, grayNameTmp}; + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), oldConfigAllInfo4Gray, + srcIp, srcUser, now, "D", Constants.GRAY, + ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(), + oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser())); + + EmbeddedStorageContextUtils.onDeleteConfigGrayInfo(tenantTmp, group, dataId, grayNameTmp, srcIp); + EmbeddedStorageContextHolder.addSqlContext(sql, args); + try { + databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext()); + } finally { + EmbeddedStorageContextHolder.cleanAllContext(); + } + } + + @Override + public ConfigOperateResult updateConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser) { + String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + + configInfo.setTenant(tenantTmp); + + try { + ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(), + configInfo.getGroup(), tenantTmp, grayNameTmp); + if (oldConfigAllInfo4Gray == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", + configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + } + } + + String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + Timestamp time = new Timestamp(System.currentTimeMillis()); + + final String sql = configInfoGrayMapper.update( + Arrays.asList("content", "md5", "src_ip", "src_user", "gmt_modified", "app_name", "gray_rule"), + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")); + final Object[] args = new Object[] {configInfo.getContent(), md5, srcIp, srcUser, time, appNameTmp, + grayRuleTmp, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp}; + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), + oldConfigAllInfo4Gray, srcIp, srcUser, now, "U", Constants.GRAY, + ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(), + oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser())); + + EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, time); + EmbeddedStorageContextHolder.addSqlContext(sql, args); + + databaseOperate.blockUpdate(); + return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + + } finally { + EmbeddedStorageContextHolder.cleanAllContext(); + } + } + + @Override + public ConfigOperateResult updateConfigInfo4GrayCas(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser) { + String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + + configInfo.setTenant(tenantTmp); + + try { + final ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(), + configInfo.getGroup(), tenantTmp, grayNameTmp); + if (oldConfigAllInfo4Gray == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", + configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + } + } + + String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + Timestamp time = new Timestamp(System.currentTimeMillis()); + + MapperContext context = new MapperContext(); + context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent()); + context.putUpdateParameter(FieldConstant.MD5, md5); + context.putUpdateParameter(FieldConstant.SRC_IP, srcIp); + context.putUpdateParameter(FieldConstant.SRC_USER, srcUser); + context.putUpdateParameter(FieldConstant.GMT_MODIFIED, time); + context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp); + + context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId()); + context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup()); + context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp); + context.putWhereParameter(FieldConstant.GRAY_NAME, grayNameTmp); + context.putWhereParameter(FieldConstant.GRAY_RULE, grayRuleTmp); + context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5()); + + final MapperResult mapperResult = configInfoGrayMapper.updateConfigInfo4GrayCas(context); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), + oldConfigAllInfo4Gray, srcIp, srcUser, now, "U", Constants.GRAY, + ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(), + oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser())); + + EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, time); + EmbeddedStorageContextHolder.addSqlContext(mapperResult.getSql(), mapperResult.getParamList().toArray()); + + Boolean success = databaseOperate.blockUpdate(); + if (success) { + return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + } else { + return new ConfigOperateResult(false); + } + + } finally { + EmbeddedStorageContextHolder.cleanAllContext(); + } + } + + @Override + public ConfigInfoGrayWrapper findConfigInfo4Gray(final String dataId, final String group, final String tenant, + final String grayName) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + final String sql = configInfoGrayMapper.select( + Arrays.asList("id", "data_id", "group_id", "tenant_id", "gray_name", "gray_rule", "app_name", "content", + "md5", "gmt_modified", "src_user", "encrypted_data_key"), + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")); + + return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp, grayNameTmp}, + CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER); + } + + @Override + public int configInfoGrayCount() { + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String sql = configInfoGrayMapper.count(null); + Integer result = databaseOperate.queryOne(sql, Integer.class); + if (result == null) { + throw new IllegalArgumentException("configInfoBetaCount error"); + } + return result; + } + + @Override + public Page findAllConfigInfoGrayForDumpAll(final int pageNo, final int pageSize) { + final int startRow = (pageNo - 1) * pageSize; + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String sqlCountRows = configInfoGrayMapper.count(null); + MapperResult sqlFetchRows = configInfoGrayMapper.findAllConfigInfoGrayForDumpAllFetchRows( + new MapperContext(startRow, pageSize)); + + PaginationHelper helper = createPaginationHelper(); + return helper.fetchPageLimit(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(), pageNo, + pageSize, CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER); + + } + + @Override + public List findConfigInfoGrays(String dataId, String group, String tenant) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + final String sql = configInfoGrayMapper.select(Collections.singletonList("gray_name"), + Arrays.asList("data_id", "group_id", "tenant_id")); + + return databaseOperate.queryMany(sql, new Object[] {dataId, group, tenantTmp}, String.class); + } + + @Override + public List findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize) { + try { + ConfigInfoGrayMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + + MapperContext context = new MapperContext(); + context.putWhereParameter(FieldConstant.START_TIME, startTime); + context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize); + context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId); + + MapperResult mapperResult = configInfoMapper.findChangeConfig(context); + return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(), + CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER); + } catch (DataAccessException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImpl.java index d547771721d..046bbb25fa6 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImpl.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImpl.java @@ -37,6 +37,8 @@ import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; +import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.config.server.utils.ParamUtils; import com.alibaba.nacos.core.distributed.id.IdGeneratorManager; import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage; @@ -219,7 +221,9 @@ private ConfigOperateResult addConfigInfo(final String srcIp, final String srcUs configInfo.getTenant()); Timestamp now = new Timestamp(System.currentTimeMillis()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, now, "I"); + historyConfigInfoPersistService.insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, now, "I", + Constants.FORMAL, ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)); + EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, now); databaseOperate.blockUpdate(consumer); return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp); @@ -266,7 +270,7 @@ public long addConfigInfoAtomic(final long id, final String srcIp, final String configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey(); ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO); - + final String sql = configInfoMapper.insert( Arrays.asList("id", "data_id", "group_id", "tenant_id", "app_name", "content", "md5", "src_ip", "src_user", "gmt_create@NOW()", "gmt_modified@NOW()", "c_desc", "c_use", "effect", @@ -400,15 +404,15 @@ public Map batchInsertOrUpdate(List configInfoLis public void removeConfigInfo(final String dataId, final String group, final String tenant, final String srcIp, final String srcUser) { final Timestamp time = new Timestamp(System.currentTimeMillis()); - ConfigInfo configInfo = findConfigInfo(dataId, group, tenant); - if (Objects.nonNull(configInfo)) { + ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(dataId, group, tenant); + if (Objects.nonNull(oldConfigAllInfo)) { try { String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; removeConfigInfoAtomic(dataId, group, tenantTmp, srcIp, srcUser); - removeTagByIdAtomic(configInfo.getId()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(configInfo.getId(), configInfo, srcIp, - srcUser, time, "D"); + removeTagByIdAtomic(oldConfigAllInfo.getId()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo, srcIp, + srcUser, time, "D", Constants.FORMAL, ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo)); EmbeddedStorageContextUtils.onDeleteConfigInfo(tenantTmp, group, dataId, srcIp, time); @@ -423,7 +427,7 @@ public void removeConfigInfo(final String dataId, final String group, final Stri } @Override - public List removeConfigInfoByIds(final List ids, final String srcIp, final String srcUser) { + public List removeConfigInfoByIds(final List ids, final String srcIp, final String srcUser) { if (CollectionUtils.isEmpty(ids)) { return null; } @@ -431,23 +435,24 @@ public List removeConfigInfoByIds(final List ids, final String final Timestamp time = new Timestamp(System.currentTimeMillis()); try { String idsStr = StringUtils.join(ids, StringUtils.COMMA); - List configInfoList = findConfigInfosByIds(idsStr); - if (CollectionUtils.isNotEmpty(configInfoList)) { + List oldConfigAllInfoList = findAllConfigInfo4Export(null, null, null, null, ids); + if (CollectionUtils.isNotEmpty(oldConfigAllInfoList)) { removeConfigInfoByIdsAtomic(idsStr); - for (ConfigInfo configInfo : configInfoList) { - removeTagByIdAtomic(configInfo.getId()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(configInfo.getId(), configInfo, srcIp, - srcUser, time, "D"); + for (ConfigAllInfo configAllInfo : oldConfigAllInfoList) { + removeTagByIdAtomic(configAllInfo.getId()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(configAllInfo.getId(), configAllInfo, + srcIp, srcUser, time, "D", Constants.FORMAL, + ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)); } } - EmbeddedStorageContextUtils.onBatchDeleteConfigInfo(configInfoList); + EmbeddedStorageContextUtils.onBatchDeleteConfigInfo(oldConfigAllInfoList); boolean result = databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext()); if (!result) { throw new NacosConfigException("Failed to config batch deletion"); } - return configInfoList; + return oldConfigAllInfoList; } finally { EmbeddedStorageContextHolder.cleanAllContext(); } @@ -496,15 +501,22 @@ public void removeConfigInfoByIdsAtomic(final String ids) { public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final String srcIp, final String srcUser, final Map configAdvanceInfo) { try { - ConfigInfo oldConfigInfo = findConfigInfo(configInfo.getDataId(), configInfo.getGroup(), + ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + if (oldConfigAllInfo == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", + configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + } + return new ConfigOperateResult(false); + } final String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); - oldConfigInfo.setTenant(tenantTmp); + oldConfigAllInfo.setTenant(tenantTmp); - String appNameTmp = oldConfigInfo.getAppName(); + String appNameTmp = oldConfigAllInfo.getAppName(); // If the appName passed by the user is not empty, the appName of the user is persisted; // otherwise, the appName of db is used. Empty string is required to clear appName if (configInfo.getAppName() == null) { @@ -516,14 +528,14 @@ public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final S String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("config_tags"); if (configTags != null) { // Delete all tags and recreate them - removeTagByIdAtomic(oldConfigInfo.getId()); - addConfigTagsRelation(oldConfigInfo.getId(), configTags, configInfo.getDataId(), configInfo.getGroup(), + removeTagByIdAtomic(oldConfigAllInfo.getId()); + addConfigTagsRelation(oldConfigAllInfo.getId(), configTags, configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); } Timestamp time = new Timestamp(System.currentTimeMillis()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigInfo.getId(), oldConfigInfo, srcIp, - srcUser, time, "U"); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo, srcIp, + srcUser, time, "U", Constants.FORMAL, ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo)); EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, time); databaseOperate.blockUpdate(); return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp); @@ -536,15 +548,21 @@ public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final S public ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, final String srcIp, final String srcUser, final Map configAdvanceInfo) { try { - ConfigInfo oldConfigInfo = findConfigInfo(configInfo.getDataId(), configInfo.getGroup(), + ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); - + if (oldConfigAllInfo == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", + configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + } + return new ConfigOperateResult(false); + } final String tenantTmp = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); - oldConfigInfo.setTenant(tenantTmp); + oldConfigAllInfo.setTenant(tenantTmp); - String appNameTmp = oldConfigInfo.getAppName(); + String appNameTmp = oldConfigAllInfo.getAppName(); // If the appName passed by the user is not empty, the appName of the user is persisted; // otherwise, the appName of db is used. Empty string is required to clear appName if (configInfo.getAppName() == null) { @@ -556,14 +574,14 @@ public ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, fina String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("config_tags"); if (configTags != null) { // Delete all tags and recreate them - removeTagByIdAtomic(oldConfigInfo.getId()); - addConfigTagsRelation(oldConfigInfo.getId(), configTags, configInfo.getDataId(), configInfo.getGroup(), + removeTagByIdAtomic(oldConfigAllInfo.getId()); + addConfigTagsRelation(oldConfigAllInfo.getId(), configTags, configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); } - + Timestamp time = new Timestamp(System.currentTimeMillis()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigInfo.getId(), oldConfigInfo, srcIp, - srcUser, time, "U"); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo, srcIp, + srcUser, time, "U", Constants.FORMAL, ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo)); EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, time); boolean success = databaseOperate.blockUpdate(); if (success) { @@ -626,7 +644,7 @@ public void updateConfigInfoAtomic(final ConfigInfo configInfo, final String src final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("schema"); final String encryptedDataKey = configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey(); - + ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO); final String sql = configInfoMapper.update( diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImpl.java index 4bfdf8ec65b..8be147fc0b0 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImpl.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImpl.java @@ -24,6 +24,7 @@ import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; import com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage; import com.alibaba.nacos.persistence.datasource.DataSourceService; import com.alibaba.nacos.persistence.datasource.DynamicDataSource; @@ -45,11 +46,11 @@ import org.springframework.stereotype.Service; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER; @@ -90,19 +91,20 @@ public PaginationHelper createPaginationHelper() { @Override public void insertConfigHistoryAtomic(long configHistoryId, ConfigInfo configInfo, String srcIp, String srcUser, - final Timestamp time, String ops) { + final Timestamp time, String ops, String publishType, String extInfo) { String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + String publishTypeTmp = StringUtils.defaultEmptyIfBlank(publishType); String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey()); HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper( dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO); final String sql = historyConfigInfoMapper.insert( Arrays.asList("id", "data_id", "group_id", "tenant_id", "app_name", "content", "md5", "src_ip", - "src_user", "gmt_modified", "op_type", "encrypted_data_key")); + "src_user", "gmt_modified", "op_type", "publish_type", "ext_info", "encrypted_data_key")); final Object[] args = new Object[] {configHistoryId, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, - appNameTmp, configInfo.getContent(), md5Tmp, srcIp, srcUser, time, ops, encryptedDataKey}; + appNameTmp, configInfo.getContent(), md5Tmp, srcIp, srcUser, time, ops, publishTypeTmp, extInfo, encryptedDataKey}; EmbeddedStorageContextHolder.addSqlContext(sql, args); } @@ -121,17 +123,32 @@ public void removeConfigHistory(final Timestamp startTime, final int limitSize) @Override public List findDeletedConfig(final Timestamp startTime, long lastMaxId, - final int pageSize) { + final int pageSize, String publishType) { HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper( dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO); MapperContext context = new MapperContext(); context.putWhereParameter(FieldConstant.START_TIME, startTime); context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize); context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId); + context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType); MapperResult mapperResult = historyConfigInfoMapper.findDeletedConfig(context); - return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(), - CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER); + List configHistoryInfos = databaseOperate.queryMany(mapperResult.getSql(), + mapperResult.getParamList().toArray(), HISTORY_DETAIL_ROW_MAPPER); + + List configInfoStateWrappers = new ArrayList<>(); + for (ConfigHistoryInfo configHistoryInfo : configHistoryInfos) { + ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper(); + configInfoStateWrapper.setId(configHistoryInfo.getId()); + configInfoStateWrapper.setDataId(configHistoryInfo.getDataId()); + configInfoStateWrapper.setGroup(configHistoryInfo.getGroup()); + configInfoStateWrapper.setTenant(configHistoryInfo.getTenant()); + configInfoStateWrapper.setMd5(configHistoryInfo.getMd5()); + configInfoStateWrapper.setLastModified(configHistoryInfo.getLastModifiedTime().getTime()); + configInfoStateWrapper.setGrayName(ConfigExtInfoUtil.extractGrayName(configHistoryInfo.getExtInfo())); + configInfoStateWrappers.add(configInfoStateWrapper); + } + return configInfoStateWrappers; } @Override @@ -161,7 +178,7 @@ public ConfigHistoryInfo detailConfigHistory(Long nid) { dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO); String sqlFetchRows = historyConfigInfoMapper.select( Arrays.asList("nid", "data_id", "group_id", "tenant_id", "app_name", "content", "md5", "src_user", - "src_ip", "op_type", "gmt_create", "gmt_modified", "encrypted_data_key"), + "src_ip", "op_type", "publish_type", "ext_info", "gmt_create", "gmt_modified", "encrypted_data_key"), Collections.singletonList("nid")); return databaseOperate.queryOne(sqlFetchRows, new Object[] {nid}, HISTORY_DETAIL_ROW_MAPPER); } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImpl.java deleted file mode 100644 index 03c7d093e1c..00000000000 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImpl.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.repository.extrnal; - -import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.utils.LogUtil; -import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage; -import com.alibaba.nacos.persistence.datasource.DataSourceService; -import com.alibaba.nacos.persistence.datasource.DynamicDataSource; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.persistence.repository.PaginationHelper; -import com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl; -import com.alibaba.nacos.plugin.datasource.MapperManager; -import com.alibaba.nacos.plugin.datasource.constants.CommonConstant; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.constants.TableConstant; -import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoAggrMapper; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; -import com.alibaba.nacos.sys.env.EnvUtil; -import org.springframework.context.annotation.Conditional; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.CannotGetJdbcConnectionException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.stereotype.Service; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionSystemException; -import org.springframework.transaction.support.TransactionTemplate; - -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_AGGR_ROW_MAPPER; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_CHANGED_ROW_MAPPER; - -/** - * ExternalConfigInfoAggrPersistServiceImpl. - * - * @author lixiaoshuang - */ -@SuppressWarnings(value = {"PMD.MethodReturnWrapperTypeRule", "checkstyle:linelength"}) -@Conditional(value = ConditionOnExternalStorage.class) -@Service("externalConfigInfoAggrPersistServiceImpl") -public class ExternalConfigInfoAggrPersistServiceImpl implements ConfigInfoAggrPersistService { - - private DataSourceService dataSourceService; - - protected JdbcTemplate jt; - - protected TransactionTemplate tjt; - - private MapperManager mapperManager; - - public ExternalConfigInfoAggrPersistServiceImpl() { - this.dataSourceService = DynamicDataSource.getInstance().getDataSource(); - this.jt = dataSourceService.getJdbcTemplate(); - this.tjt = dataSourceService.getTransactionTemplate(); - Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class, - false); - this.mapperManager = MapperManager.instance(isDataSourceLogEnable); - } - - @Override - public PaginationHelper createPaginationHelper() { - return new ExternalStoragePaginationHelperImpl<>(jt); - } - - @Override - public boolean addAggrConfigInfo(final String dataId, final String group, String tenant, final String datumId, - String appName, final String content) { - String appNameTmp = StringUtils.isBlank(appName) ? StringUtils.EMPTY : appName; - String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; - final Timestamp now = new Timestamp(System.currentTimeMillis()); - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - String select = configInfoAggrMapper.select(Collections.singletonList("content"), - Arrays.asList("data_id", "group_id", "tenant_id", "datum_id")); - String insert = configInfoAggrMapper.insert( - Arrays.asList("data_id", "group_id", "tenant_id", "datum_id", "app_name", "content", "gmt_modified")); - String update = configInfoAggrMapper.update(Arrays.asList("content", "gmt_modified"), - Arrays.asList("data_id", "group_id", "tenant_id", "datum_id")); - - try { - try { - String dbContent = jt.queryForObject(select, new Object[] {dataId, group, tenantTmp, datumId}, - String.class); - - if (dbContent != null && dbContent.equals(content)) { - return true; - } else { - return jt.update(update, content, now, dataId, group, tenantTmp, datumId) > 0; - } - } catch (EmptyResultDataAccessException ex) { // no data, insert - return jt.update(insert, dataId, group, tenantTmp, datumId, appNameTmp, content, now) > 0; - } - } catch (DataAccessException e) { - LogUtil.FATAL_LOG.error("[db-error] " + e, e); - throw e; - } - } - - @Override - public boolean batchPublishAggr(final String dataId, final String group, final String tenant, - final Map datumMap, final String appName) { - try { - Boolean isPublishOk = tjt.execute(status -> { - for (Map.Entry entry : datumMap.entrySet()) { - try { - if (!addAggrConfigInfo(dataId, group, tenant, entry.getKey(), appName, entry.getValue())) { - throw new TransactionSystemException("error in batchPublishAggr"); - } - } catch (Throwable e) { - throw new TransactionSystemException("error in batchPublishAggr"); - } - } - return Boolean.TRUE; - }); - if (isPublishOk == null) { - return false; - } - return isPublishOk; - } catch (TransactionException e) { - LogUtil.FATAL_LOG.error("[db-error] " + e, e); - return false; - } - } - - @Override - public int aggrConfigInfoCount(String dataId, String group, String tenant) { - String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - String sql = configInfoAggrMapper.count(Arrays.asList("data_id", "group_id", "tenant_id")); - Integer result = jt.queryForObject(sql, Integer.class, new Object[] {dataId, group, tenantTmp}); - return result.intValue(); - } - - @Override - public Page findConfigInfoAggrByPage(String dataId, String group, String tenant, final int pageNo, - final int pageSize) { - String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - final int startRow = (pageNo - 1) * pageSize; - String sqlCountRows = configInfoAggrMapper.select(Arrays.asList("count(*)"), - Arrays.asList("data_id", "group_id", "tenant_id")); - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, group); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp); - context.setStartRow(startRow); - context.setPageSize(pageSize); - - MapperResult mapperResult = configInfoAggrMapper.findConfigInfoAggrByPageFetchRows(context); - String sqlFetchRows = mapperResult.getSql(); - Object[] sqlFetchArgs = mapperResult.getParamList().toArray(); - - PaginationHelper helper = this.createPaginationHelper(); - try { - return helper.fetchPageLimit(sqlCountRows, new Object[] {dataId, group, tenantTmp}, sqlFetchRows, - sqlFetchArgs, pageNo, pageSize, CONFIG_INFO_AGGR_ROW_MAPPER); - - } catch (CannotGetJdbcConnectionException e) { - LogUtil.FATAL_LOG.error("[db-error] " + e, e); - throw e; - } - } - - @Override - public List findAllAggrGroup() { - ConfigInfoAggrMapper configInfoAggrMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), - TableConstant.CONFIG_INFO_AGGR); - MapperResult mapperResult = configInfoAggrMapper.findAllAggrGroupByDistinct(null); - - try { - return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), - CONFIG_INFO_CHANGED_ROW_MAPPER); - } catch (CannotGetJdbcConnectionException e) { - LogUtil.FATAL_LOG.error("[db-error] " + e, e); - throw e; - } catch (EmptyResultDataAccessException e) { - return null; - } catch (Exception e) { - LogUtil.FATAL_LOG.error("[db-other-error]" + e.getMessage(), e); - throw new RuntimeException(e); - } - } - -} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImpl.java new file mode 100644 index 00000000000..a19bc2e840f --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImpl.java @@ -0,0 +1,408 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.repository.extrnal; + +import com.alibaba.nacos.common.utils.MD5Utils; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.config.server.constant.Constants; +import com.alibaba.nacos.config.server.model.ConfigInfo; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; +import com.alibaba.nacos.config.server.model.ConfigOperateResult; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; +import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; +import com.alibaba.nacos.config.server.utils.LogUtil; +import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage; +import com.alibaba.nacos.persistence.datasource.DataSourceService; +import com.alibaba.nacos.persistence.datasource.DynamicDataSource; +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.persistence.repository.PaginationHelper; +import com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl; +import com.alibaba.nacos.plugin.datasource.MapperManager; +import com.alibaba.nacos.plugin.datasource.constants.CommonConstant; +import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; +import com.alibaba.nacos.plugin.datasource.constants.TableConstant; +import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper; +import com.alibaba.nacos.plugin.datasource.model.MapperContext; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Conditional; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; + +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER; +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; + + +/** + * ExternalConfigInfoGrayPersistServiceImpl. + * + * @author rong + */ +@SuppressWarnings(value = {"PMD.MethodReturnWrapperTypeRule", "checkstyle:linelength"}) +@Conditional(value = ConditionOnExternalStorage.class) +@Service("externalConfigInfoGrayPersistServiceImpl") +public class ExternalConfigInfoGrayPersistServiceImpl implements ConfigInfoGrayPersistService { + + private DataSourceService dataSourceService; + + protected JdbcTemplate jt; + + protected TransactionTemplate tjt; + + private MapperManager mapperManager; + + private HistoryConfigInfoPersistService historyConfigInfoPersistService; + + public ExternalConfigInfoGrayPersistServiceImpl( + @Qualifier("externalHistoryConfigInfoPersistServiceImpl") HistoryConfigInfoPersistService historyConfigInfoPersistService) { + this.historyConfigInfoPersistService = historyConfigInfoPersistService; + this.dataSourceService = DynamicDataSource.getInstance().getDataSource(); + this.jt = dataSourceService.getJdbcTemplate(); + this.tjt = dataSourceService.getTransactionTemplate(); + Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class, + false); + this.mapperManager = MapperManager.instance(isDataSourceLogEnable); + } + + @Override + public PaginationHelper createPaginationHelper() { + return new ExternalStoragePaginationHelperImpl<>(jt); + } + + @Override + public ConfigInfoStateWrapper findConfigInfo4GrayState(final String dataId, final String group, final String tenant, + String grayName) { + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + try { + return this.jt.queryForObject(configInfoGrayMapper.select( + Arrays.asList("id", "data_id", "group_id", "tenant_id", "gray_rule", "gmt_modified"), + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")), + new Object[] {dataId, group, tenantTmp, grayNameTmp}, CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER); + } catch (EmptyResultDataAccessException e) { + return null; + } + } + + private ConfigOperateResult getGrayOperateResult(String dataId, String group, String tenant, String grayName) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + + ConfigInfoStateWrapper configInfo4Gray = this.findConfigInfo4GrayState(dataId, group, tenantTmp, grayName); + if (configInfo4Gray == null) { + return new ConfigOperateResult(false); + } + return new ConfigOperateResult(configInfo4Gray.getId(), configInfo4Gray.getLastModified()); + + } + + @Override + public ConfigOperateResult addConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, String srcIp, + String srcUser) { + return tjt.execute(status -> { + String tenantTmp = + StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant().trim(); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + try { + addConfigInfoGrayAtomic(-1, configInfo, grayNameTmp, grayRuleTmp, srcIp, srcUser); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(0, configInfo, srcIp, srcUser, now, "I", + Constants.GRAY, ConfigExtInfoUtil.getExtInfoFromGrayInfo(grayNameTmp, grayRuleTmp, srcUser)); + + return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + } catch (Exception e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + }); + } + + @Override + public void addConfigInfoGrayAtomic(long configGrayId, ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser) { + String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + final String encryptedDataKey = + configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey(); + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + jt.update(configInfoGrayMapper.insert( + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name", "gray_rule", "app_name", "content", + "encrypted_data_key", "md5", "src_ip", "src_user", "gmt_create@NOW()", "gmt_modified@NOW()")), + configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayName, grayRule, appNameTmp, + configInfo.getContent(), encryptedDataKey, md5, srcIp, srcUser); + } + + @Override + public ConfigOperateResult insertOrUpdateGray(final ConfigInfo configInfo, final String grayName, + final String grayRule, final String srcIp, final String srcUser) { + if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName) + == null) { + return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser); + } else { + return updateConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser); + } + } + + @Override + public ConfigOperateResult insertOrUpdateGrayCas(final ConfigInfo configInfo, final String grayName, + final String grayRule, final String srcIp, final String srcUser) { + if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName) + == null) { + return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser); + } else { + return updateConfigInfo4GrayCas(configInfo, grayName, grayRule, srcIp, srcUser); + } + } + + @Override + public void removeConfigInfoGray(final String dataId, final String group, final String tenant, + final String grayName, final String srcIp, final String srcUser) { + tjt.execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus status) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName; + try { + ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(dataId, group, tenantTmp, + grayNameTmp); + if (oldConfigAllInfo4Gray == null) { + return; + } + + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper( + dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_GRAY); + jt.update( + configInfoGrayMapper.delete(Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")), + dataId, group, tenantTmp, grayNameTmp); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), + oldConfigAllInfo4Gray, srcIp, srcUser, now, "D", Constants.GRAY, + ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(), + oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser())); + } catch (CannotGetJdbcConnectionException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + } + }); + } + + @Override + public ConfigOperateResult updateConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser) { + return tjt.execute(status -> { + String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + try { + ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(), + configInfo.getGroup(), tenantTmp, grayNameTmp); + if (oldConfigAllInfo4Gray == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", + configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + } + } + + String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper( + dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_GRAY); + jt.update(configInfoGrayMapper.update( + Arrays.asList("content", "encrypted_data_key", "md5", "src_ip", "src_user", + "gmt_modified@NOW()", "app_name", "gray_rule"), + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")), configInfo.getContent(), + configInfo.getEncryptedDataKey(), md5, srcIp, srcUser, appNameTmp, grayRuleTmp, + configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), + oldConfigAllInfo4Gray, srcIp, srcUser, now, "U", Constants.GRAY, + ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(), + oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser())); + + return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + } catch (CannotGetJdbcConnectionException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + }); + } + + @Override + public ConfigOperateResult updateConfigInfo4GrayCas(ConfigInfo configInfo, String grayName, String grayRule, + String srcIp, String srcUser) { + return tjt.execute(status -> { + String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); + String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim(); + try { + String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper( + dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_GRAY); + Timestamp time = new Timestamp(System.currentTimeMillis()); + + MapperContext context = new MapperContext(); + context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent()); + context.putUpdateParameter(FieldConstant.MD5, md5); + context.putUpdateParameter(FieldConstant.SRC_IP, srcIp); + context.putUpdateParameter(FieldConstant.SRC_USER, srcUser); + context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp); + + context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId()); + context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup()); + context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp); + context.putWhereParameter(FieldConstant.GRAY_NAME, grayNameTmp); + context.putWhereParameter(FieldConstant.GRAY_RULE, grayRuleTmp); + context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5()); + + final MapperResult mapperResult = configInfoGrayMapper.updateConfigInfo4GrayCas(context); + boolean success = jt.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) > 0; + + ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(), + configInfo.getGroup(), tenantTmp, grayNameTmp); + if (oldConfigAllInfo4Gray == null) { + if (LogUtil.FATAL_LOG.isErrorEnabled()) { + LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", + configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); + } + } + + Timestamp now = new Timestamp(System.currentTimeMillis()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), + oldConfigAllInfo4Gray, srcIp, srcUser, now, "U", Constants.GRAY, + ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(), + oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser())); + + if (success) { + return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp); + } else { + return new ConfigOperateResult(false); + } + } catch (CannotGetJdbcConnectionException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + }); + } + + @Override + public ConfigInfoGrayWrapper findConfigInfo4Gray(final String dataId, final String group, final String tenant, + final String grayName) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim(); + try { + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + return this.jt.queryForObject(configInfoGrayMapper.select( + Arrays.asList("id", "data_id", "group_id", "tenant_id", "gray_name", "gray_rule", "app_name", + "content", "md5", "encrypted_data_key", "gmt_modified", "src_user"), + Arrays.asList("data_id", "group_id", "tenant_id", "gray_name")), + new Object[] {dataId, group, tenantTmp, grayNameTmp}, CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER); + } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null. + return null; + } catch (CannotGetJdbcConnectionException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + } + + @Override + public int configInfoGrayCount() { + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String sql = configInfoGrayMapper.count(null); + Integer result = jt.queryForObject(sql, Integer.class); + if (result == null) { + throw new IllegalArgumentException("configInfoGrayCount error"); + } + return result; + } + + @Override + public Page findAllConfigInfoGrayForDumpAll(final int pageNo, final int pageSize) { + final int startRow = (pageNo - 1) * pageSize; + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String sqlCountRows = configInfoGrayMapper.count(null); + MapperResult sqlFetchRows = configInfoGrayMapper.findAllConfigInfoGrayForDumpAllFetchRows( + new MapperContext(startRow, pageSize)); + + PaginationHelper helper = createPaginationHelper(); + + try { + return helper.fetchPageLimit(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(), + pageNo, pageSize, CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER); + + } catch (CannotGetJdbcConnectionException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + } + + @Override + public List findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize) { + try { + ConfigInfoGrayMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + + MapperContext context = new MapperContext(); + context.putWhereParameter(FieldConstant.START_TIME, startTime); + context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize); + context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId); + + MapperResult mapperResult = configInfoMapper.findChangeConfig(context); + return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), + CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER); + } catch (DataAccessException e) { + LogUtil.FATAL_LOG.error("[db-error] " + e, e); + throw e; + } + } + + @Override + public List findConfigInfoGrays(final String dataId, final String group, final String tenant) { + String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant; + ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), + TableConstant.CONFIG_INFO_GRAY); + String selectSql = configInfoGrayMapper.select(Collections.singletonList("gray_name"), + Arrays.asList("data_id", "group_id", "tenant_id")); + return jt.queryForList(selectSql, new Object[] {dataId, group, tenantTmp}, String.class); + } + +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java index b768c83c8c3..1f04f57a4c3 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java @@ -34,6 +34,7 @@ import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.config.server.utils.ParamUtils; import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage; @@ -150,7 +151,8 @@ public ConfigOperateResult addConfigInfo(final String srcIp, final String srcUse configInfo.getTenant()); Timestamp now = new Timestamp(System.currentTimeMillis()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(0, configInfo, srcIp, srcUser, now, "I"); + historyConfigInfoPersistService.insertConfigHistoryAtomic(0, configInfo, srcIp, srcUser, now, "I", + Constants.FORMAL, ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)); ConfigInfoStateWrapper configInfoCurrent = this.findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); if (configInfoCurrent == null) { @@ -397,12 +399,12 @@ public void removeConfigInfo(final String dataId, final String group, final Stri @Override public Boolean doInTransaction(TransactionStatus status) { try { - ConfigInfo configInfo = findConfigInfo(dataId, group, tenant); - if (configInfo != null) { + ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(dataId, group, tenant); + if (oldConfigAllInfo != null) { removeConfigInfoAtomic(dataId, group, tenant, srcIp, srcUser); - removeTagByIdAtomic(configInfo.getId()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(configInfo.getId(), configInfo, srcIp, - srcUser, time, "D"); + removeTagByIdAtomic(oldConfigAllInfo.getId()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo, + srcIp, srcUser, time, "D", Constants.FORMAL, ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo)); } } catch (CannotGetJdbcConnectionException e) { LogUtil.FATAL_LOG.error("[db-error] " + e, e); @@ -414,28 +416,29 @@ public Boolean doInTransaction(TransactionStatus status) { } @Override - public List removeConfigInfoByIds(final List ids, final String srcIp, final String srcUser) { + public List removeConfigInfoByIds(final List ids, final String srcIp, final String srcUser) { if (CollectionUtils.isEmpty(ids)) { return null; } ids.removeAll(Collections.singleton(null)); - return tjt.execute(new TransactionCallback>() { + return tjt.execute(new TransactionCallback>() { final Timestamp time = new Timestamp(System.currentTimeMillis()); @Override - public List doInTransaction(TransactionStatus status) { + public List doInTransaction(TransactionStatus status) { try { String idsStr = StringUtils.join(ids, StringUtils.COMMA); - List configInfoList = findConfigInfosByIds(idsStr); - if (!CollectionUtils.isEmpty(configInfoList)) { + List oldConfigAllInfoList = findAllConfigInfo4Export(null, null, null, null, ids); + if (!CollectionUtils.isEmpty(oldConfigAllInfoList)) { removeConfigInfoByIdsAtomic(idsStr); - for (ConfigInfo configInfo : configInfoList) { - removeTagByIdAtomic(configInfo.getId()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(configInfo.getId(), configInfo, - srcIp, srcUser, time, "D"); + for (ConfigAllInfo configAllInfo : oldConfigAllInfoList) { + removeTagByIdAtomic(configAllInfo.getId()); + historyConfigInfoPersistService.insertConfigHistoryAtomic(configAllInfo.getId(), + configAllInfo, srcIp, srcUser, time, "D", Constants.FORMAL, + ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)); } } - return configInfoList; + return oldConfigAllInfoList; } catch (CannotGetJdbcConnectionException e) { LogUtil.FATAL_LOG.error("[db-error] " + e, e); throw e; @@ -499,9 +502,9 @@ public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final S final Map configAdvanceInfo) { return tjt.execute(status -> { try { - ConfigInfo oldConfigInfo = findConfigInfo(configInfo.getDataId(), configInfo.getGroup(), + ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); - if (oldConfigInfo == null) { + if (oldConfigAllInfo == null) { if (LogUtil.FATAL_LOG.isErrorEnabled()) { LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); @@ -509,7 +512,7 @@ public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final S return new ConfigOperateResult(false); } - String appNameTmp = oldConfigInfo.getAppName(); + String appNameTmp = oldConfigAllInfo.getAppName(); /* If the appName passed by the user is not empty, use the persistent user's appName, otherwise use db; when emptying appName, you need to pass an empty string @@ -521,14 +524,14 @@ public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final S String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("config_tags"); if (configTags != null) { // delete all tags and then recreate - removeTagByIdAtomic(oldConfigInfo.getId()); - addConfigTagsRelation(oldConfigInfo.getId(), configTags, configInfo.getDataId(), + removeTagByIdAtomic(oldConfigAllInfo.getId()); + addConfigTagsRelation(oldConfigAllInfo.getId(), configTags, configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); } - + Timestamp now = new Timestamp(System.currentTimeMillis()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigInfo.getId(), oldConfigInfo, srcIp, - srcUser, now, "U"); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo, srcIp, srcUser, + now, "U", Constants.FORMAL, ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo)); return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); } catch (CannotGetJdbcConnectionException e) { @@ -552,16 +555,16 @@ public ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, fina final String srcUser, final Map configAdvanceInfo) { return tjt.execute(status -> { try { - ConfigInfo oldConfigInfo = findConfigInfo(configInfo.getDataId(), configInfo.getGroup(), + ConfigAllInfo oldAllConfigInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); - if (oldConfigInfo == null) { + if (oldAllConfigInfo == null) { if (LogUtil.FATAL_LOG.isErrorEnabled()) { LogUtil.FATAL_LOG.error("expected config info[dataid:{}, group:{}, tenent:{}] but not found.", configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); } return new ConfigOperateResult(false); } - String appNameTmp = oldConfigInfo.getAppName(); + String appNameTmp = oldAllConfigInfo.getAppName(); /* If the appName passed by the user is not empty, use the persistent user's appName, otherwise use db; when emptying appName, you need to pass an empty string @@ -576,14 +579,14 @@ public ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, fina String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get("config_tags"); if (configTags != null) { // delete all tags and then recreate - removeTagByIdAtomic(oldConfigInfo.getId()); - addConfigTagsRelation(oldConfigInfo.getId(), configTags, configInfo.getDataId(), + removeTagByIdAtomic(oldAllConfigInfo.getId()); + addConfigTagsRelation(oldAllConfigInfo.getId(), configTags, configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); } Timestamp now = new Timestamp(System.currentTimeMillis()); - historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigInfo.getId(), oldConfigInfo, srcIp, - srcUser, now, "U"); + historyConfigInfoPersistService.insertConfigHistoryAtomic(oldAllConfigInfo.getId(), oldAllConfigInfo, srcIp, srcUser, now, + "U", Constants.FORMAL, ConfigExtInfoUtil.getExtInfoFromAllInfo(oldAllConfigInfo)); ConfigInfoStateWrapper configInfoLast = this.findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()); if (configInfoLast == null) { @@ -612,7 +615,7 @@ private int updateConfigInfoAtomicCas(final ConfigInfo configInfo, final String try { ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO); - + MapperContext context = new MapperContext(); context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent()); context.putUpdateParameter(FieldConstant.MD5, md5Tmp); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImpl.java b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImpl.java index eeec61d6130..00df35b8667 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImpl.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImpl.java @@ -23,6 +23,7 @@ import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; import com.alibaba.nacos.config.server.utils.LogUtil; import com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage; import com.alibaba.nacos.persistence.datasource.DataSourceService; @@ -46,11 +47,11 @@ import org.springframework.transaction.support.TransactionTemplate; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER; @@ -88,20 +89,21 @@ public PaginationHelper createPaginationHelper() { @Override public void insertConfigHistoryAtomic(long id, ConfigInfo configInfo, String srcIp, String srcUser, - final Timestamp time, String ops) { + final Timestamp time, String ops, String publishType, String extInfo) { String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName()); String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant()); final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE); String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey()); + String publishTypeTmp = StringUtils.defaultEmptyIfBlank(publishType); try { HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper( dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO); jt.update(historyConfigInfoMapper.insert( Arrays.asList("id", "data_id", "group_id", "tenant_id", "app_name", "content", "md5", "src_ip", - "src_user", "gmt_modified", "op_type", "encrypted_data_key")), id, configInfo.getDataId(), - configInfo.getGroup(), tenantTmp, appNameTmp, configInfo.getContent(), md5Tmp, srcIp, srcUser, time, - ops, encryptedDataKey); + "src_user", "gmt_modified", "op_type", "publish_type", "ext_info", "encrypted_data_key")), + id, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, appNameTmp, configInfo.getContent(), + md5Tmp, srcIp, srcUser, time, ops, publishTypeTmp, extInfo, encryptedDataKey); } catch (DataAccessException e) { LogUtil.FATAL_LOG.error("[db-error] " + e, e); throw e; @@ -121,7 +123,8 @@ public void removeConfigHistory(final Timestamp startTime, final int limitSize) } @Override - public List findDeletedConfig(final Timestamp startTime, long startId, int pageSize) { + public List findDeletedConfig(final Timestamp startTime, long startId, int pageSize, + String publishType) { try { HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper( dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO); @@ -129,10 +132,25 @@ public List findDeletedConfig(final Timestamp startTime, context.putWhereParameter(FieldConstant.START_TIME, startTime); context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize); context.putWhereParameter(FieldConstant.LAST_MAX_ID, startId); + context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType); MapperResult mapperResult = historyConfigInfoMapper.findDeletedConfig(context); - return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), - CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER); + List configHistoryInfos = jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), + HISTORY_DETAIL_ROW_MAPPER); + + List configInfoStateWrappers = new ArrayList<>(); + for (ConfigHistoryInfo configHistoryInfo : configHistoryInfos) { + ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper(); + configInfoStateWrapper.setId(configHistoryInfo.getId()); + configInfoStateWrapper.setDataId(configHistoryInfo.getDataId()); + configInfoStateWrapper.setGroup(configHistoryInfo.getGroup()); + configInfoStateWrapper.setTenant(configHistoryInfo.getTenant()); + configInfoStateWrapper.setMd5(configHistoryInfo.getMd5()); + configInfoStateWrapper.setLastModified(configHistoryInfo.getLastModifiedTime().getTime()); + configInfoStateWrapper.setGrayName(ConfigExtInfoUtil.extractGrayName(configHistoryInfo.getExtInfo())); + configInfoStateWrappers.add(configInfoStateWrapper); + } + return configInfoStateWrappers; } catch (DataAccessException e) { LogUtil.FATAL_LOG.error("[db-error] " + e, e); throw e; @@ -174,7 +192,7 @@ public ConfigHistoryInfo detailConfigHistory(Long nid) { dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO); String sqlFetchRows = historyConfigInfoMapper.select( Arrays.asList("nid", "data_id", "group_id", "tenant_id", "app_name", "content", "md5", "src_user", - "src_ip", "op_type", "gmt_create", "gmt_modified", "encrypted_data_key"), + "src_ip", "op_type", "gmt_create", "gmt_modified", "publish_type", "ext_info", "encrypted_data_key"), Collections.singletonList("nid")); try { ConfigHistoryInfo historyInfo = jt.queryForObject(sqlFetchRows, new Object[] {nid}, diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/sql/EmbeddedStorageContextUtils.java b/config/src/main/java/com/alibaba/nacos/config/server/service/sql/EmbeddedStorageContextUtils.java index dac6777617f..ecd06f734f7 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/sql/EmbeddedStorageContextUtils.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/sql/EmbeddedStorageContextUtils.java @@ -19,6 +19,7 @@ import com.alibaba.nacos.common.utils.JacksonUtils; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.config.server.constant.Constants; +import com.alibaba.nacos.config.server.model.ConfigAllInfo; import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.event.ConfigDumpEvent; import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; @@ -102,6 +103,29 @@ public static void onModifyConfigTagInfo(ConfigInfo configInfo, String tag, Stri } } + /** + * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously + * via the raft state machine, along with the information. + * + * @param configInfo {@link ConfigInfo} + * @param grayName gray name + * @param grayRule gray rule + * @param srcIp The IP of the operator + * @param time Operating time + */ + public static void onModifyConfigGrayInfo(ConfigInfo configInfo, String grayName, String grayRule, String srcIp, Timestamp time) { + if (!EnvUtil.getStandaloneMode()) { + ConfigDumpEvent event = ConfigDumpEvent.builder().remove(false).namespaceId(configInfo.getTenant()) + .dataId(configInfo.getDataId()).group(configInfo.getGroup()).isBeta(false).grayName(grayName) + .grayRule(grayRule).content(configInfo.getContent()).type(configInfo.getType()).handleIp(srcIp) + .lastModifiedTs(time.getTime()).build(); + + Map extendInfo = new HashMap<>(2); + extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event)); + EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo); + } + } + /** * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously * via the raft state machine, along with the information. @@ -128,12 +152,12 @@ public static void onDeleteConfigInfo(String namespaceId, String group, String d * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously * via the raft state machine, along with the information. * - * @param configInfos {@link ConfigInfo} list + * @param configInfos {@link ConfigAllInfo} list */ - public static void onBatchDeleteConfigInfo(List configInfos) { + public static void onBatchDeleteConfigInfo(List configInfos) { if (!EnvUtil.getStandaloneMode()) { List events = new ArrayList<>(); - for (ConfigInfo configInfo : configInfos) { + for (ConfigAllInfo configInfo : configInfos) { String namespaceId = StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant(); ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId) @@ -190,4 +214,25 @@ public static void onDeleteConfigTagInfo(String namespaceId, String group, Strin } } + /** + * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously + * via the raft state machine, along with the information. + * + * @param namespaceId namespaceId + * @param group group + * @param dataId dataId + * @param grayName gray name + * @param srcIp The IP of the operator + */ + public static void onDeleteConfigGrayInfo(String namespaceId, String group, String dataId, String grayName, + String srcIp) { + if (!EnvUtil.getStandaloneMode()) { + ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId).group(group) + .dataId(dataId).isBeta(true).grayName(grayName).handleIp(srcIp).build(); + + Map extendInfo = new HashMap<>(2); + extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event)); + EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo); + } + } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java index ec9b4a58fcc..5133e14c478 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java @@ -41,8 +41,6 @@ public class ConfigTraceService { public static final String PERSISTENCE_EVENT_BETA = "persist-beta"; - public static final String PERSISTENCE_EVENT_BATCH = "persist-batch"; - public static final String PERSISTENCE_EVENT_TAG = "persist-tag"; /** @@ -101,12 +99,6 @@ public class ConfigTraceService { */ public static final String PULL_EVENT = "pull"; - public static final String PULL_EVENT_BETA = "pull-beta"; - - public static final String PULL_EVENT_BATCH = "pull-batch"; - - public static final String PULL_EVENT_TAG = "pull-tag"; - /** * pull type. */ @@ -197,22 +189,10 @@ public static void logDumpEvent(String dataId, String group, String tenant, Stri delayed, length); } - public static void logDumpBetaEvent(String dataId, String group, String tenant, String requestIpAppName, long ts, - String handleIp, String type, long delayed, long length) { - logDumpEventInner(dataId, group, tenant, requestIpAppName, ts, handleIp, ConfigTraceService.DUMP_EVENT_BETA, - type, delayed, length); - } - - public static void logDumpBatchEvent(String dataId, String group, String tenant, String requestIpAppName, long ts, - String handleIp, String type, long delayed, long length) { - logDumpEventInner(dataId, group, tenant, requestIpAppName, ts, handleIp, ConfigTraceService.DUMP_EVENT_BATCH, - type, delayed, length); - } - - public static void logDumpTagEvent(String dataId, String group, String tenant, String tag, String requestIpAppName, - long ts, String handleIp, String type, long delayed, long length) { + public static void logDumpGrayNameEvent(String dataId, String group, String tenant, String grayName, + String requestIpAppName, long ts, String handleIp, String type, long delayed, long length) { logDumpEventInner(dataId, group, tenant, requestIpAppName, ts, handleIp, - ConfigTraceService.DUMP_EVENT_TAG + "-" + tag, type, delayed, length); + ConfigTraceService.DUMP_EVENT + "-" + grayName, type, delayed, length); } private static void logDumpEventInner(String dataId, String group, String tenant, String requestIpAppName, long ts, diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtil.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtil.java new file mode 100644 index 00000000000..1e7c49e87a3 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtil.java @@ -0,0 +1,190 @@ +/* + * Copyright 1999-$toady.year Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.utils; + +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.config.server.constant.Constants; +import com.alibaba.nacos.config.server.model.ConfigAllInfo; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * Extra info util. + * + * @author Nacos + */ +public class ConfigExtInfoUtil { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigExtInfoUtil.class); + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private static final Map EXTRA_INFO_KEYS_MAPPING = new HashMap<>(); + + static { + EXTRA_INFO_KEYS_MAPPING.put("type", "type"); + EXTRA_INFO_KEYS_MAPPING.put("config_tags", "config_tags"); + EXTRA_INFO_KEYS_MAPPING.put("src_user", "src_user"); + EXTRA_INFO_KEYS_MAPPING.put("desc", "c_desc"); + EXTRA_INFO_KEYS_MAPPING.put("use", "c_use"); + EXTRA_INFO_KEYS_MAPPING.put("effect", "effect"); + EXTRA_INFO_KEYS_MAPPING.put("schema", "c_schema"); + } + + private ConfigExtInfoUtil() { + } + + /** + * Extract the extInfo from advance config info. + */ + public static String getExtraInfoFromAdvanceInfoMap(Map advanceConfigInfoMap, String srcUser) { + try { + if (advanceConfigInfoMap == null || advanceConfigInfoMap.isEmpty()) { + return null; + } + + ObjectNode node = OBJECT_MAPPER.createObjectNode(); + + if (StringUtils.isNotBlank(srcUser)) { + node.put("src_user", srcUser); + } + + for (Map.Entry entry : EXTRA_INFO_KEYS_MAPPING.entrySet()) { + String key = entry.getKey(); + String mappedKey = entry.getValue(); + Object advanceConfigInfoValue = advanceConfigInfoMap.get(key); + if (advanceConfigInfoValue instanceof String && StringUtils.isNotBlank( + (String) advanceConfigInfoValue)) { + node.put(mappedKey, ((String) advanceConfigInfoValue).trim()); + } + } + + return OBJECT_MAPPER.writeValueAsString(node); + } catch (Exception ex) { + LOGGER.error("Failed to get extra info from advance info map", ex); + return null; + } + } + + /** + * Extract the extInfo from all config info. + */ + public static String getExtInfoFromAllInfo(ConfigAllInfo configAllInfo) { + ObjectNode node = OBJECT_MAPPER.createObjectNode(); + + if (StringUtils.isNotBlank(configAllInfo.getType())) { + node.put("type", configAllInfo.getType()); + } + if (StringUtils.isNotBlank(configAllInfo.getConfigTags())) { + node.put("config_tags", configAllInfo.getConfigTags()); + } + if (StringUtils.isNotBlank(configAllInfo.getEffect())) { + node.put("effect", configAllInfo.getEffect()); + } + if (StringUtils.isNotBlank(configAllInfo.getCreateUser())) { + node.put("src_user", configAllInfo.getCreateUser()); + } + if (StringUtils.isNotBlank(configAllInfo.getDesc())) { + node.put("c_desc", configAllInfo.getDesc()); + } + if (StringUtils.isNotBlank(configAllInfo.getUse())) { + node.put("c_use", configAllInfo.getUse()); + } + if (StringUtils.isNotBlank(configAllInfo.getSchema())) { + node.put("c_schema", configAllInfo.getSchema()); + } + + try { + return OBJECT_MAPPER.writeValueAsString(node); + } catch (Exception ex) { + LOGGER.error("Failed to get extra info from all config info", ex); + return null; + } + } + + /** + * Extract the extInfo from gray config info. + */ + public static String getExtInfoFromGrayInfo(String grayName, String grayRuleTmp, String oldSrcUser) { + ObjectNode node = OBJECT_MAPPER.createObjectNode(); + ObjectNode grayRuleNode = OBJECT_MAPPER.createObjectNode(); + + if (StringUtils.isNotBlank(grayName)) { + node.put("gray_name", grayName); + } + + if (StringUtils.isNotBlank(oldSrcUser)) { + node.put("src_user", oldSrcUser); + } + + if (StringUtils.isNotBlank(grayRuleTmp)) { + try { + JsonNode parsedGrayRuleNode = OBJECT_MAPPER.readTree(grayRuleTmp); + if (parsedGrayRuleNode.has(Constants.GRAY_RULE_TYPE)) { + grayRuleNode.put(Constants.GRAY_RULE_TYPE, + parsedGrayRuleNode.get(Constants.GRAY_RULE_TYPE).asText()); + } + if (parsedGrayRuleNode.has(Constants.GRAY_RULE_EXPR)) { + grayRuleNode.put(Constants.GRAY_RULE_EXPR, + parsedGrayRuleNode.get(Constants.GRAY_RULE_EXPR).asText()); + } + if (parsedGrayRuleNode.has(Constants.GRAY_RULE_VERSION)) { + grayRuleNode.put(Constants.GRAY_RULE_VERSION, + parsedGrayRuleNode.get(Constants.GRAY_RULE_VERSION).asText()); + } + if (parsedGrayRuleNode.has(Constants.GRAY_RULE_PRIORITY)) { + grayRuleNode.put(Constants.GRAY_RULE_PRIORITY, + parsedGrayRuleNode.get(Constants.GRAY_RULE_PRIORITY).asText()); + } + node.put("gray_rule", grayRuleNode.toString()); + } catch (Exception ex) { + LOGGER.error("Failed to parse gray rule as json", ex); + return null; + } + } + + try { + return OBJECT_MAPPER.writeValueAsString(node); + } catch (Exception ex) { + LOGGER.error("Failed to serialize extra info from gray info", ex); + return null; + } + } + + /** + * Extract grayName from extInfo. + */ + public static String extractGrayName(String extraInfo) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + Map dataMap = objectMapper.readValue(extraInfo, new TypeReference>() { + }); + return dataMap.get("gray_name"); + } catch (Exception e) { + LogUtil.DEFAULT_LOG.error("Error extracting gray_name from extraInfo", e); + return null; + } + } + +} \ No newline at end of file diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java index c0633c2061f..9d9faa84a91 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; +import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; import static com.alibaba.nacos.config.server.constant.Constants.LINE_SEPARATOR; import static com.alibaba.nacos.config.server.constant.Constants.WORD_SEPARATOR; @@ -52,7 +53,7 @@ public class MD5Util { public static List compareMd5(HttpServletRequest request, HttpServletResponse response, Map clientMd5Map) { List changedGroupKeys = new ArrayList<>(); - String tag = request.getHeader("Vipserver-Tag"); + String tag = request.getHeader(VIPSERVER_TAG); for (Map.Entry entry : clientMd5Map.entrySet()) { String groupKey = entry.getKey(); String clientMd5 = entry.getValue(); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/PropertyUtil.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/PropertyUtil.java index 76837e4e215..678918fd29c 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/utils/PropertyUtil.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/PropertyUtil.java @@ -55,6 +55,11 @@ public class PropertyUtil implements ApplicationContextInitializer resultInfos = new ArrayList<>(); + final List resultInfos = new ArrayList<>(); + ConfigAllInfo configAllInfo = new ConfigAllInfo(); String dataId = "dataId1123"; String group = "group34567"; String tenant = "tenant45678"; - resultInfos.add(new ConfigInfo(dataId, group, tenant)); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + resultInfos.add(configAllInfo); Mockito.when(configInfoPersistService.removeConfigInfoByIds(eq(Arrays.asList(1L, 2L)), anyString(), eq(null))) .thenReturn(resultInfos); AtomicReference reference = new AtomicReference<>(); @@ -200,8 +211,8 @@ public Class subscribeType() { } }); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_CONTROLLER_PATH).param("delType", "ids") - .param("ids", "1,2"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_CONTROLLER_PATH) + .param("delType", "ids").param("ids", "1,2"); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); @@ -224,8 +235,9 @@ void testGetConfigAdvanceInfo() throws Exception { when(configInfoPersistService.findConfigAdvanceInfo("test", "test", "")).thenReturn(configAdvanceInfo); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH + "/catalog") - .param("dataId", "test").param("group", "test").param("tenant", ""); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get( + Constants.CONFIG_CONTROLLER_PATH + "/catalog").param("dataId", "test").param("group", "test") + .param("tenant", ""); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); String code = JacksonUtils.toObj(actualValue).get("code").toString(); @@ -240,8 +252,8 @@ void testGetConfigAdvanceInfo() throws Exception { @Test void testListener() throws Exception { - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.CONFIG_CONTROLLER_PATH + "/listener") - .param("Listening-Configs", "test"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post( + Constants.CONFIG_CONTROLLER_PATH + "/listener").param("Listening-Configs", "test"); int actualValue = mockmvc.perform(builder).andReturn().getResponse().getStatus(); assertEquals(200, actualValue); } @@ -255,11 +267,13 @@ void testGetListeners() throws Exception { when(configSubService.getCollectSampleResult("test", "test", "", 1)).thenReturn(sampleResult); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH + "/listener") - .param("dataId", "test").param("group", "test").param("tenant", "").param("sampleTime", "1"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get( + Constants.CONFIG_CONTROLLER_PATH + "/listener").param("dataId", "test").param("group", "test") + .param("tenant", "").param("sampleTime", "1"); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); - GroupkeyListenserStatus groupkeyListenserStatus = JacksonUtils.toObj(actualValue, GroupkeyListenserStatus.class); + GroupkeyListenserStatus groupkeyListenserStatus = JacksonUtils.toObj(actualValue, + GroupkeyListenserStatus.class); assertEquals(200, groupkeyListenserStatus.getCollectStatus()); assertEquals(1, groupkeyListenserStatus.getLisentersGroupkeyStatus().size()); assertEquals("test", groupkeyListenserStatus.getLisentersGroupkeyStatus().get("test")); @@ -278,11 +292,12 @@ void testSearchConfig() throws Exception { page.setPageItems(configInfoList); Map configAdvanceInfo = new HashMap<>(8); - when(configInfoPersistService.findConfigInfo4Page(1, 10, "test", "test", "", configAdvanceInfo)).thenReturn(page); + when(configInfoPersistService.findConfigInfo4Page(1, 10, "test", "test", "", configAdvanceInfo)).thenReturn( + page); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH).param("search", "accurate") - .param("dataId", "test").param("group", "test").param("appName", "").param("tenant", "").param("config_tags", "") - .param("pageNo", "1").param("pageSize", "10"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH) + .param("search", "accurate").param("dataId", "test").param("group", "test").param("appName", "") + .param("tenant", "").param("config_tags", "").param("pageNo", "1").param("pageSize", "10"); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); @@ -310,16 +325,18 @@ void testFuzzySearchConfig() throws Exception { page.setPageItems(configInfoList); Map configAdvanceInfo = new HashMap<>(8); - when(configInfoPersistService.findConfigInfoLike4Page(1, 10, "test", "test", "", configAdvanceInfo)).thenReturn(page); + when(configInfoPersistService.findConfigInfoLike4Page(1, 10, "test", "test", "", configAdvanceInfo)).thenReturn( + page); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH).param("search", "blur") - .param("dataId", "test").param("group", "test").param("appName", "").param("tenant", "").param("config_tags", "") - .param("pageNo", "1").param("pageSize", "10"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH) + .param("search", "blur").param("dataId", "test").param("group", "test").param("appName", "") + .param("tenant", "").param("config_tags", "").param("pageNo", "1").param("pageSize", "10"); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); List resultList = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("pageItems").toString(), List.class); - ConfigInfo resConfigInfo = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("pageItems").get(0).toString(), ConfigInfo.class); + ConfigInfo resConfigInfo = JacksonUtils.toObj( + JacksonUtils.toObj(actualValue).get("pageItems").get(0).toString(), ConfigInfo.class); assertEquals(configInfoList.size(), resultList.size()); assertEquals(configInfo.getDataId(), resConfigInfo.getDataId()); @@ -330,8 +347,8 @@ void testFuzzySearchConfig() throws Exception { @Test void testStopBeta() throws Exception { - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_CONTROLLER_PATH).param("beta", "true") - .param("dataId", "test").param("group", "test").param("tenant", ""); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_CONTROLLER_PATH) + .param("beta", "true").param("dataId", "test").param("group", "test").param("tenant", ""); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); @@ -344,15 +361,17 @@ void testStopBeta() throws Exception { @Test void testQueryBeta() throws Exception { - ConfigInfoBetaWrapper configInfoBetaWrapper = new ConfigInfoBetaWrapper(); + ConfigInfoGrayWrapper configInfoBetaWrapper = new ConfigInfoGrayWrapper(); configInfoBetaWrapper.setDataId("test"); configInfoBetaWrapper.setGroup("test"); configInfoBetaWrapper.setContent("test"); + configInfoBetaWrapper.setGrayName("beta"); + configInfoBetaWrapper.setGrayRule("{\"type\":\"beta\",\"version\":\"1.0.0\",\"expr\":\"127.0.0.1,127.0.0.2\",\"priority\":-1000}"); + when(configInfoGrayPersistService.findConfigInfo4Gray("test", "test", "", "beta")).thenReturn( + configInfoBetaWrapper); - when(configInfoBetaPersistService.findConfigInfo4Beta("test", "test", "")).thenReturn(configInfoBetaWrapper); - - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH).param("beta", "true") - .param("dataId", "test").param("group", "test").param("tenant", ""); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH) + .param("beta", "true").param("dataId", "test").param("group", "test").param("tenant", ""); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); String code = JacksonUtils.toObj(actualValue).get("code").toString(); @@ -363,6 +382,8 @@ void testQueryBeta() throws Exception { assertEquals(configInfoBetaWrapper.getDataId(), resConfigInfoBetaWrapper.getDataId()); assertEquals(configInfoBetaWrapper.getGroup(), resConfigInfoBetaWrapper.getGroup()); assertEquals(configInfoBetaWrapper.getContent(), resConfigInfoBetaWrapper.getContent()); + assertEquals("127.0.0.1,127.0.0.2", resConfigInfoBetaWrapper.getBetaIps()); + } @Test @@ -383,8 +404,9 @@ void testExportConfig() throws Exception { Mockito.when(configInfoPersistService.findAllConfigInfo4Export(eq(dataId), eq(group), eq(tenant), eq(appname), eq(Arrays.asList(1L, 2L)))).thenReturn(dataList); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH).param("export", "true") - .param("dataId", dataId).param("group", group).param("tenant", tenant).param("appName", appname).param("ids", "1,2"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH) + .param("export", "true").param("dataId", dataId).param("group", group).param("tenant", tenant) + .param("appName", appname).param("ids", "1,2"); int actualValue = mockmvc.perform(builder).andReturn().getResponse().getStatus(); @@ -407,8 +429,9 @@ void testExportConfigV2() throws Exception { dataList.add(configAllInfo); Mockito.when(configInfoPersistService.findAllConfigInfo4Export(eq(dataId), eq(group), eq(tenant), eq(appname), eq(Arrays.asList(1L, 2L)))).thenReturn(dataList); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH).param("exportV2", "true") - .param("dataId", dataId).param("group", group).param("tenant", tenant).param("appName", appname).param("ids", "1,2"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_CONTROLLER_PATH) + .param("exportV2", "true").param("dataId", dataId).param("group", group).param("tenant", tenant) + .param("appName", appname).param("ids", "1,2"); int actualValue = mockmvc.perform(builder).andReturn().getResponse().getStatus(); @@ -428,16 +451,19 @@ void testImportAndPublishConfig() throws Exception { when(namespacePersistService.tenantInfoCountByTenantId("public")).thenReturn(1); Map map = new HashMap<>(); map.put("test", "test"); - when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(), any())).thenReturn(map); + when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(), + any())).thenReturn(map); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(Constants.CONFIG_CONTROLLER_PATH).file(file) - .param("import", "true").param("src_user", "test").param("namespace", "public").param("policy", "ABORT"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(Constants.CONFIG_CONTROLLER_PATH) + .file(file).param("import", "true").param("src_user", "test").param("namespace", "public") + .param("policy", "ABORT"); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); String code = JacksonUtils.toObj(actualValue).get("code").toString(); assertEquals("200", code); - Map resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("data").toString(), Map.class); + Map resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("data").toString(), + Map.class); assertEquals(map.get("test"), resultMap.get("test").toString()); zipUtilsMockedStatic.close(); @@ -467,16 +493,19 @@ void testImportAndPublishConfigV2() throws Exception { when(namespacePersistService.tenantInfoCountByTenantId("public")).thenReturn(1); Map map = new HashMap<>(); map.put("test", "test"); - when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(), any())).thenReturn(map); + when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(), + any())).thenReturn(map); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(Constants.CONFIG_CONTROLLER_PATH).file(file) - .param("import", "true").param("src_user", "test").param("namespace", "public").param("policy", "ABORT"); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(Constants.CONFIG_CONTROLLER_PATH) + .file(file).param("import", "true").param("src_user", "test").param("namespace", "public") + .param("policy", "ABORT"); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); String code = JacksonUtils.toObj(actualValue).get("code").toString(); assertEquals("200", code); - Map resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("data").toString(), Map.class); + Map resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("data").toString(), + Map.class); assertEquals(map.get("test"), resultMap.get("test").toString()); zipUtilsMockedStatic.close(); @@ -502,21 +531,24 @@ void testCloneConfig() throws Exception { List idList = new ArrayList<>(configBeansList.size()); idList.add(sameNamespaceCloneConfigBean.getCfgId()); - when(configInfoPersistService.findAllConfigInfo4Export(null, null, null, null, idList)).thenReturn(queryedDataList); + when(configInfoPersistService.findAllConfigInfo4Export(null, null, null, null, idList)).thenReturn( + queryedDataList); Map map = new HashMap<>(); map.put("test", "test"); - when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(), any())).thenReturn(map); + when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(), + any())).thenReturn(map); - MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.CONFIG_CONTROLLER_PATH).param("clone", "true") - .param("src_user", "test").param("tenant", "public").param("policy", "ABORT").content(JacksonUtils.toJson(configBeansList)) - .contentType(MediaType.APPLICATION_JSON); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.CONFIG_CONTROLLER_PATH) + .param("clone", "true").param("src_user", "test").param("tenant", "public").param("policy", "ABORT") + .content(JacksonUtils.toJson(configBeansList)).contentType(MediaType.APPLICATION_JSON); String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString(); String code = JacksonUtils.toObj(actualValue).get("code").toString(); assertEquals("200", code); - Map resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("data").toString(), Map.class); + Map resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get("data").toString(), + Map.class); assertEquals(map.get("test"), resultMap.get("test").toString()); } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java index 115c39abe2a..651ca61fb84 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java @@ -20,8 +20,14 @@ import com.alibaba.nacos.common.constant.HttpHeaderConsts; import com.alibaba.nacos.common.http.param.MediaType; import com.alibaba.nacos.common.utils.JacksonUtils; +import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.config.server.constant.Constants; import com.alibaba.nacos.config.server.model.CacheItem; +import com.alibaba.nacos.config.server.model.ConfigCacheGray; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.LongPollingService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; @@ -54,6 +60,8 @@ import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; import static com.alibaba.nacos.config.server.constant.Constants.CONTENT_MD5; +import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_GBK; +import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; import static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_HEADER; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -143,33 +151,55 @@ void testDoGetConfigV1Beta() throws Exception { //mock cache item isBeta CacheItem cacheItem = new CacheItem("test"); - cacheItem.setBeta(true); - List ips4Beta = new ArrayList<>(); - ips4Beta.add("localhost"); - cacheItem.setIps4Beta(ips4Beta); - cacheItem.initBetaCacheIfEmpty(); - cacheItem.getConfigCacheBeta().setEncryptedDataKey("betaKey1234567"); - cacheItem.getConfigCacheBeta().setMd5Utf8("md52345Beta"); String dataId = "testDataId135"; String group = "group23"; String tenant = "tenant234"; - configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant))) + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant))) .thenReturn(cacheItem); - + String mockBetaContent = "content3456543"; + mockGray4Beta(cacheItem, mockBetaContent, "localhost", "betaKey1234567"); MockHttpServletRequest request = new MockHttpServletRequest(); request.setRemoteAddr("localhost:8080"); request.addHeader(CLIENT_APPNAME_HEADER, "test"); MockHttpServletResponse response = new MockHttpServletResponse(); - String mockBetaContent = "content3456543"; - when(configRocksDbDiskService.getBetaContent(dataId, group, tenant)).thenReturn(mockBetaContent); - String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, "", "true", "localhost"); + + when(configRocksDbDiskService.getGrayContent(dataId, group, tenant, BetaGrayRule.TYPE_BETA)).thenReturn( + mockBetaContent); + String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, "", "true", + "localhost"); assertEquals(HttpServletResponse.SC_OK + "", actualValue); assertEquals("true", response.getHeader("isBeta")); - assertEquals("md52345Beta", response.getHeader(CONTENT_MD5)); + assertEquals(MD5Utils.md5Hex(mockBetaContent, ENCODE_UTF8), response.getHeader(CONTENT_MD5)); assertEquals("betaKey1234567", response.getHeader("Encrypted-Data-Key")); assertEquals(mockBetaContent, response.getContentAsString()); } + private void mockGray4Beta(CacheItem cacheItem, String content, String betaIps, String dataKey) { + cacheItem.initConfigGrayIfEmpty(BetaGrayRule.TYPE_BETA); + ConfigCacheGray configCacheGray = cacheItem.getConfigCacheGray().get(BetaGrayRule.TYPE_BETA); + configCacheGray.setMd5Utf8(MD5Utils.md5Hex(content, ENCODE_UTF8)); + configCacheGray.setMd5Gbk(MD5Utils.md5Hex(content, ENCODE_GBK)); + configCacheGray.setEncryptedDataKey(dataKey); + ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA, + BetaGrayRule.VERSION, betaIps, -1000); + configCacheGray.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo)); + cacheItem.sortConfigGray(); + } + + private void mockGray4Tag(CacheItem cacheItem, String content, String tagValue, String dataKey, long ts) { + cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + "_" + tagValue); + ConfigCacheGray configCacheGray = cacheItem.getConfigCacheGray().get(TagGrayRule.TYPE_TAG + "_" + tagValue); + configCacheGray.setMd5Utf8(MD5Utils.md5Hex(content, ENCODE_UTF8)); + configCacheGray.setMd5Gbk(MD5Utils.md5Hex(content, ENCODE_GBK)); + configCacheGray.setLastModifiedTs(ts); + configCacheGray.setEncryptedDataKey(dataKey); + ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, + TagGrayRule.VERSION, tagValue, -999); + configCacheGray.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo)); + cacheItem.sortConfigGray(); + } + /** * test get config of tag. * @@ -181,29 +211,23 @@ void testDoGetConfigV1Tag() throws Exception { String dataId = "dataId123455"; String group = "group"; String tenant = "tenant"; - configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))) - .thenReturn(1); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1); //mock cache item with tag. CacheItem cacheItem = new CacheItem("test"); - cacheItem.setBeta(false); - List ips4Beta = new ArrayList<>(); - ips4Beta.add("localhost"); - cacheItem.setIps4Beta(ips4Beta); String autoTag = "auto-tag-test"; - cacheItem.initConfigTagsIfEmpty(autoTag); - cacheItem.getConfigCacheTags().get(autoTag).setEncryptedDataKey("autoTagkey"); - cacheItem.getConfigCacheTags().get(autoTag).setMd5Utf8("md5autotag11"); long autoTagTs = System.currentTimeMillis(); - cacheItem.getConfigCacheTags().get(autoTag).setLastModifiedTs(autoTagTs); + String autoTagContent = "1234566autotag"; + mockGray4Tag(cacheItem, autoTagContent, autoTag, "autoTagkey", autoTagTs); + String specificTag = "specificTag"; - cacheItem.initConfigTagsIfEmpty(specificTag); - cacheItem.getConfigCacheTags().get(specificTag).setEncryptedDataKey("specificTagkey"); - cacheItem.getConfigCacheTags().get(specificTag).setMd5Utf8("md5specificTag11"); + String specificTagContent = "1234566autotag"; long specificTs = System.currentTimeMillis(); - cacheItem.getConfigCacheTags().get(specificTag).setLastModifiedTs(specificTs); + mockGray4Tag(cacheItem, specificTagContent, specificTag, "specificTagkey", specificTs); - configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant))) + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant))) .thenReturn(cacheItem); //test auto tag. @@ -212,29 +236,34 @@ void testDoGetConfigV1Tag() throws Exception { request.addHeader(CLIENT_APPNAME_HEADER, "test"); request.addHeader(VIPSERVER_TAG, autoTag); MockHttpServletResponse response = new MockHttpServletResponse(); - String autoTagContent = "1234566autotag"; - Mockito.when(configRocksDbDiskService.getTagContent(dataId, group, tenant, autoTag)).thenReturn(autoTagContent); - String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true", "localhost"); + + Mockito.when( + configRocksDbDiskService.getGrayContent(dataId, group, tenant, TagGrayRule.TYPE_TAG + "_" + autoTag)) + .thenReturn(autoTagContent); + String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true", + "localhost"); assertEquals(HttpServletResponse.SC_OK + "", actualValue); assertEquals(autoTagContent, response.getContentAsString()); - assertEquals("md5autotag11", response.getHeader(CONTENT_MD5)); + assertEquals(MD5Utils.md5Hex(autoTagContent, "UTF-8"), response.getHeader(CONTENT_MD5)); assertEquals("autoTagkey", response.getHeader("Encrypted-Data-Key")); //test for specific tag. has higher propority than auto tag. response = new MockHttpServletResponse(); - String specificTagContent = "1234566autotag"; - when(configRocksDbDiskService.getTagContent(dataId, group, tenant, specificTag)).thenReturn(specificTagContent); - actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, specificTag, "true", "localhost"); + when(configRocksDbDiskService.getGrayContent(dataId, group, tenant, + TagGrayRule.TYPE_TAG + "_" + specificTag)).thenReturn(specificTagContent); + actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, specificTag, "true", + "localhost"); assertEquals(HttpServletResponse.SC_OK + "", actualValue); assertEquals(specificTagContent, response.getContentAsString()); - assertEquals("md5specificTag11", response.getHeader(CONTENT_MD5)); + assertEquals(MD5Utils.md5Hex(specificTagContent, "UTF-8"), response.getHeader(CONTENT_MD5)); assertEquals("specificTagkey", response.getHeader("Encrypted-Data-Key")); // test for specific tag ,not exist - when(configRocksDbDiskService.getTagContent(dataId, group, tenant, "auto-tag-test-not-exist")).thenReturn(null); + when(configRocksDbDiskService.getGrayContent(dataId, group, tenant, + TagGrayRule.TYPE_TAG + "_" + "auto-tag-test-not-exist")).thenReturn(null); response = new MockHttpServletResponse(); - actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, "auto-tag-test-not-exist", "true", - "localhost"); + actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, + "auto-tag-test-not-exist", "true", "localhost"); assertEquals(HttpServletResponse.SC_NOT_FOUND + "", actualValue); String expectedContent = "config data not exist"; String actualContent = response.getContentAsString(); @@ -248,25 +277,26 @@ void testDoGetConfigFormal() throws Exception { String dataId = "dataId1234552333"; String group = "group"; String tenant = "tenant"; - configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))) - .thenReturn(1); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1); //mock cache item . CacheItem cacheItem = new CacheItem("test"); - cacheItem.setBeta(false); String md5 = "md5wertyui"; String content = "content345678"; cacheItem.getConfigCache().setMd5Utf8(md5); long ts = System.currentTimeMillis(); cacheItem.getConfigCache().setLastModifiedTs(ts); cacheItem.getConfigCache().setEncryptedDataKey("key2345678"); - configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant))) + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant))) .thenReturn(cacheItem); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); when(configRocksDbDiskService.getContent(dataId, group, tenant)).thenReturn(content); - String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true", "localhost"); + String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true", + "localhost"); assertEquals(content, response.getContentAsString()); assertEquals(HttpServletResponse.SC_OK + "", actualValue); assertEquals(md5, response.getHeader(CONTENT_MD5)); @@ -279,25 +309,26 @@ void testDoGetConfigFormalV2() throws Exception { String dataId = "dataId1234552333V2"; String group = "group"; String tenant = "tenant"; - configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))) - .thenReturn(1); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1); //mock cache item . CacheItem cacheItem = new CacheItem("test"); - cacheItem.setBeta(false); String md5 = "md5wertyui"; String content = "content345678"; cacheItem.getConfigCache().setMd5Utf8(md5); long ts = System.currentTimeMillis(); cacheItem.getConfigCache().setLastModifiedTs(ts); cacheItem.getConfigCache().setEncryptedDataKey("key2345678"); - configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant))) + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant))) .thenReturn(cacheItem); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); when(configRocksDbDiskService.getContent(dataId, group, tenant)).thenReturn(content); - String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true", "localhost", true); + String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, "true", + "localhost", true); assertEquals(JacksonUtils.toJson(Result.success(content)), response.getContentAsString()); assertEquals(HttpServletResponse.SC_OK + "", actualValue); assertEquals(md5, response.getHeader(CONTENT_MD5)); @@ -312,14 +343,17 @@ void testDoGetConfigNotExist() throws Exception { configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(0); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); - String actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true", "localhost"); + String actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true", + "localhost"); assertEquals(HttpServletResponse.SC_NOT_FOUND + "", actualValue); - configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(GroupKey2.getKey("test", "test", "test"))) + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.getContentCache(GroupKey2.getKey("test", "test", "test"))) .thenReturn(new CacheItem(GroupKey2.getKey("test", "test", "test"))); // if lockResult less than 0 configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(-1); - actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true", "localhost"); + actualValue = configServletInner.doGetConfig(request, response, "test", "test", "test", "test", "true", + "localhost"); assertEquals(HttpServletResponse.SC_CONFLICT + "", actualValue); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandlerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandlerTest.java index 81e7aad105d..15771287e6a 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandlerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandlerTest.java @@ -21,6 +21,7 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.request.RequestMeta; import com.alibaba.nacos.api.remote.response.ResponseCode; +import com.alibaba.nacos.config.server.service.ConfigGrayModelMigrateService; import com.alibaba.nacos.config.server.service.dump.DumpService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,6 +32,8 @@ import java.io.IOException; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class ConfigChangeClusterSyncRequestHandlerTest { @@ -40,9 +43,13 @@ class ConfigChangeClusterSyncRequestHandlerTest { @Mock private DumpService dumpService; + @Mock + private ConfigGrayModelMigrateService configGrayModelMigrateService; + @BeforeEach void setUp() throws IOException { - configChangeClusterSyncRequestHandler = new ConfigChangeClusterSyncRequestHandler(dumpService); + configChangeClusterSyncRequestHandler = new ConfigChangeClusterSyncRequestHandler(dumpService, + configGrayModelMigrateService); } @Test @@ -59,4 +66,41 @@ void testHandle() throws NacosException { configChangeSyncRequest, meta); assertEquals(configChangeClusterSyncResponse.getResultCode(), ResponseCode.SUCCESS.getCode()); } + + @Test + void testHandleBetaCompatibleFromOldServer() throws NacosException { + ConfigChangeClusterSyncRequest configChangeSyncRequest = new ConfigChangeClusterSyncRequest(); + configChangeSyncRequest.setRequestId(""); + configChangeSyncRequest.setDataId("dataId"); + configChangeSyncRequest.setGroup("group123"); + configChangeSyncRequest.setTenant("tenant..."); + configChangeSyncRequest.setLastModified(1L); + configChangeSyncRequest.setBeta(true); + RequestMeta meta = new RequestMeta(); + meta.setClientIp("1.1.1.1"); + ConfigChangeClusterSyncResponse configChangeClusterSyncResponse = configChangeClusterSyncRequestHandler.handle( + configChangeSyncRequest, meta); + verify(configGrayModelMigrateService, times(1)).checkMigrateBeta(configChangeSyncRequest.getDataId(), + configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant()); + assertEquals(configChangeClusterSyncResponse.getResultCode(), ResponseCode.SUCCESS.getCode()); + } + + @Test + void testHandleOldCompatibleFromOldServer() throws NacosException { + ConfigChangeClusterSyncRequest configChangeSyncRequest = new ConfigChangeClusterSyncRequest(); + configChangeSyncRequest.setRequestId(""); + configChangeSyncRequest.setDataId("dataId"); + configChangeSyncRequest.setGroup("group123"); + configChangeSyncRequest.setTenant("tenant..."); + configChangeSyncRequest.setTag("tag1234"); + configChangeSyncRequest.setLastModified(1L); + RequestMeta meta = new RequestMeta(); + meta.setClientIp("1.1.1.1"); + ConfigChangeClusterSyncResponse configChangeClusterSyncResponse = configChangeClusterSyncRequestHandler.handle( + configChangeSyncRequest, meta); + verify(configGrayModelMigrateService, times(1)).checkMigrateTag(configChangeSyncRequest.getDataId(), + configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(), + configChangeSyncRequest.getTag()); + assertEquals(configChangeClusterSyncResponse.getResultCode(), ResponseCode.SUCCESS.getCode()); + } } \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandlerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandlerTest.java index d5ffb5c0a38..f4074c41e6e 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandlerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandlerTest.java @@ -29,8 +29,10 @@ import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; import com.alibaba.nacos.config.server.model.ConfigOperateResult; import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; -import com.alibaba.nacos.config.server.service.AggrWhitelist; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.service.ConfigOperationService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration; @@ -49,9 +51,9 @@ import java.util.concurrent.atomic.AtomicReference; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -67,7 +69,8 @@ class ConfigPublishRequestHandlerTest { @Mock ConfigInfoTagPersistService configInfoTagPersistService; - MockedStatic aggrWhitelistMockedStatic; + @Mock + ConfigInfoGrayPersistService configInfoGrayPersistService; MockedStatic envUtilMockedStatic; @@ -75,18 +78,16 @@ class ConfigPublishRequestHandlerTest { @BeforeEach void setUp() { - aggrWhitelistMockedStatic = Mockito.mockStatic(AggrWhitelist.class); envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); - - configPublishRequestHandler = new ConfigPublishRequestHandler(configInfoPersistService, configInfoTagPersistService, - configInfoBetaPersistService); + ConfigOperationService configOperationService = new ConfigOperationService(configInfoPersistService, + configInfoTagPersistService, configInfoBetaPersistService, configInfoGrayPersistService); + configPublishRequestHandler = new ConfigPublishRequestHandler(configOperationService); DatasourceConfiguration.setEmbeddedStorage(false); } @AfterEach void after() { - aggrWhitelistMockedStatic.close(); envUtilMockedStatic.close(); } @@ -149,8 +150,6 @@ public Class subscribeType() { assertEquals(group, reference.get().group); assertEquals(tenant, reference.get().tenant); assertEquals(timestamp, reference.get().lastModifiedTs); - assertFalse(reference.get().isBatch); - assertFalse(reference.get().isBeta); } @@ -203,8 +202,8 @@ public Class subscribeType() { long id = timestamp / 1000; configOperateResult.setId(id); configOperateResult.setLastModified(timestamp); - when(configInfoPersistService.insertOrUpdateCas(eq(requestMeta.getClientIp()), eq(srcUser), any(ConfigInfo.class), - any(Map.class))).thenReturn(configOperateResult); + when(configInfoPersistService.insertOrUpdateCas(eq(requestMeta.getClientIp()), eq(srcUser), + any(ConfigInfo.class), any(Map.class))).thenReturn(configOperateResult); ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode()); @@ -214,8 +213,6 @@ public Class subscribeType() { assertEquals(group, reference.get().group); assertEquals(tenant, reference.get().tenant); assertEquals(timestamp, reference.get().lastModifiedTs); - assertFalse(reference.get().isBatch); - assertFalse(reference.get().isBeta); } /** @@ -272,8 +269,8 @@ public Class subscribeType() { long id = timestamp / 1000; configOperateResult.setId(id); configOperateResult.setLastModified(timestamp); - when(configInfoPersistService.insertOrUpdateCas(eq(requestMeta.getClientIp()), eq(srcUser), any(ConfigInfo.class), - any(Map.class))).thenThrow(new NacosRuntimeException(502, "mock error")); + when(configInfoPersistService.insertOrUpdateCas(eq(requestMeta.getClientIp()), eq(srcUser), + any(ConfigInfo.class), any(Map.class))).thenThrow(new NacosRuntimeException(502, "mock error")); ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode()); @@ -283,48 +280,6 @@ public Class subscribeType() { } - @Test - void testPublishAggrCheckFail() throws NacosException, InterruptedException { - - RequestMeta requestMeta = new RequestMeta(); - String clientIp = "127.0.0.1"; - requestMeta.setClientIp(clientIp); - - String dataId = "testPublishAggrCheckFail"; - String group = "group"; - String tenant = "tenant"; - String content = "content"; - ConfigPublishRequest configPublishRequest = new ConfigPublishRequest(); - configPublishRequest.setDataId(dataId); - configPublishRequest.setGroup(group); - configPublishRequest.setTenant(tenant); - configPublishRequest.setContent(content); - when(AggrWhitelist.isAggrDataId(eq(dataId))).thenReturn(Boolean.TRUE); - - AtomicReference reference = new AtomicReference<>(); - NotifyCenter.registerSubscriber(new Subscriber() { - - @Override - public void onEvent(Event event) { - ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event; - if (event1.dataId.equals(dataId)) { - reference.set((ConfigDataChangeEvent) event); - } - } - - @Override - public Class subscribeType() { - return ConfigDataChangeEvent.class; - } - }); - ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); - - assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode()); - assertTrue(response.getMessage().contains("is aggr")); - Thread.sleep(500L); - assertTrue(reference.get() == null); - } - @Test void testBetaPublishNotCas() throws NacosException, InterruptedException { String dataId = "testBetaPublish"; @@ -370,8 +325,10 @@ public Class subscribeType() { long id = timestamp / 1000; configOperateResult.setId(id); configOperateResult.setLastModified(timestamp); - when(configInfoBetaPersistService.insertOrUpdateBeta(any(ConfigInfo.class), eq(betaIps), eq(requestMeta.getClientIp()), - eq(srcUser))).thenReturn(configOperateResult); + when(configInfoBetaPersistService.insertOrUpdateBeta(any(ConfigInfo.class), eq(betaIps), + eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq(BetaGrayRule.TYPE_BETA), + anyString(), eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult); ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode()); @@ -381,8 +338,7 @@ public Class subscribeType() { assertEquals(group, reference.get().group); assertEquals(tenant, reference.get().tenant); assertEquals(timestamp, reference.get().lastModifiedTs); - assertFalse(reference.get().isBatch); - assertTrue(reference.get().isBeta); + assertEquals("beta", reference.get().grayName); } @@ -432,8 +388,10 @@ public Class subscribeType() { long id = timestamp / 1000; configOperateResult.setId(id); configOperateResult.setLastModified(timestamp); - when(configInfoBetaPersistService.insertOrUpdateBetaCas(any(ConfigInfo.class), eq(betaIps), eq(requestMeta.getClientIp()), - eq(srcUser))).thenReturn(configOperateResult); + when(configInfoBetaPersistService.insertOrUpdateBetaCas(any(ConfigInfo.class), eq(betaIps), + eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq(BetaGrayRule.TYPE_BETA), + anyString(), eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult); ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode()); @@ -443,8 +401,8 @@ public Class subscribeType() { assertEquals(group, reference.get().group); assertEquals(tenant, reference.get().tenant); assertEquals(timestamp, reference.get().lastModifiedTs); - assertFalse(reference.get().isBatch); - assertTrue(reference.get().isBeta); + assertEquals(tenant, reference.get().tenant); + assertEquals("beta", reference.get().grayName); } @@ -495,9 +453,10 @@ public Class subscribeType() { long id = timestamp / 1000; configOperateResult.setId(id); configOperateResult.setLastModified(timestamp); - when(configInfoTagPersistService.insertOrUpdateTag(any(ConfigInfo.class), eq(tag), eq(requestMeta.getClientIp()), - eq(srcUser))).thenReturn(configOperateResult); - + when(configInfoTagPersistService.insertOrUpdateTag(any(ConfigInfo.class), eq(tag), + eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq("tag_" + tag), anyString(), + eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult); ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode()); @@ -507,9 +466,8 @@ public Class subscribeType() { assertEquals(group, reference.get().group); assertEquals(tenant, reference.get().tenant); assertEquals(timestamp, reference.get().lastModifiedTs); - assertFalse(reference.get().isBatch); - assertFalse(reference.get().isBeta); - assertEquals(tag, reference.get().tag); + + assertEquals("tag_" + tag, reference.get().grayName); } @@ -554,9 +512,10 @@ public Class subscribeType() { long id = timestamp / 1000; configOperateResult.setId(id); configOperateResult.setLastModified(timestamp); - when(configInfoTagPersistService.insertOrUpdateTagCas(any(ConfigInfo.class), eq(tag), eq(requestMeta.getClientIp()), - eq(srcUser))).thenReturn(configOperateResult); - + when(configInfoTagPersistService.insertOrUpdateTagCas(any(ConfigInfo.class), eq(tag), + eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq("tag_" + tag), anyString(), + eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult); ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta); assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode()); @@ -566,10 +525,7 @@ public Class subscribeType() { assertEquals(group, reference.get().group); assertEquals(tenant, reference.get().tenant); assertEquals(timestamp, reference.get().lastModifiedTs); - assertFalse(reference.get().isBatch); - assertFalse(reference.get().isBeta); - assertEquals(tag, reference.get().tag); - + assertEquals("tag_" + tag, reference.get().grayName); } } \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java index 6467ad8e948..7762f6f56c0 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java @@ -21,7 +21,11 @@ import com.alibaba.nacos.api.remote.request.RequestMeta; import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.config.server.model.CacheItem; -import com.alibaba.nacos.config.server.model.ConfigCache; +import com.alibaba.nacos.config.server.model.ConfigCacheGray; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; +import com.alibaba.nacos.config.server.model.gray.TagGrayRule; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; import com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService; @@ -38,7 +42,6 @@ import org.springframework.core.env.StandardEnvironment; import java.io.IOException; -import java.util.Arrays; import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; import static com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse.CONFIG_NOT_FOUND; @@ -140,14 +143,16 @@ void testGetBeta() throws Exception { when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService); CacheItem cacheItem = new CacheItem(groupKey); - cacheItem.initBetaCacheIfEmpty(); + cacheItem.initConfigGrayIfEmpty(BetaGrayRule.TYPE_BETA); String content = "content_from_beta_notdirectreadÄãºÃ" + System.currentTimeMillis(); - cacheItem.getConfigCacheBeta().setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); - cacheItem.getConfigCacheBeta().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); - cacheItem.getConfigCacheBeta().setEncryptedDataKey("key_testGetBeta_NotDirectRead"); - cacheItem.setBeta(true); - cacheItem.setIps4Beta(Arrays.asList("127.0.0.1")); - + ConfigCacheGray configCacheGrayBeta = cacheItem.getConfigCacheGray().get(BetaGrayRule.TYPE_BETA); + configCacheGrayBeta.setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); + configCacheGrayBeta.setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); + configCacheGrayBeta.setEncryptedDataKey("key_testGetBeta_NotDirectRead"); + ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA, + BetaGrayRule.VERSION, "127.0.0.1", -1000); + configCacheGrayBeta.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo)); + cacheItem.sortConfigGray(); when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem); ConfigQueryRequest configQueryRequest = new ConfigQueryRequest(); @@ -156,7 +161,8 @@ void testGetBeta() throws Exception { RequestMeta requestMeta = new RequestMeta(); requestMeta.setClientIp("127.0.0.1"); - when(configRocksDbDiskService.getBetaContent(eq(dataId), eq(group), eq(null))).thenReturn(content); + when(configRocksDbDiskService.getGrayContent(eq(dataId), eq(group), eq(null), + eq(BetaGrayRule.TYPE_BETA))).thenReturn(content); ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta); //check content&md5 assertEquals(content, response.getContent()); @@ -229,16 +235,19 @@ void testGetTagWithTag() throws Exception { cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); cacheItem.getConfigCache().setEncryptedDataKey("key_formal"); - ConfigCache configCacheTag = new ConfigCache(); + String specificTag = "specific_tag"; + cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + "_" + specificTag); + ConfigCacheGray configCacheGrayTag = cacheItem.getConfigCacheGray() + .get(TagGrayRule.TYPE_TAG + "_" + specificTag); String tagContent = "content_from_specific_tag_directreadÄãºÃ" + System.currentTimeMillis(); - configCacheTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK")); - configCacheTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8")); - configCacheTag.setEncryptedDataKey("key_testGetTag_NotDirectRead"); - cacheItem.initConfigTagsIfEmpty(); + configCacheGrayTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK")); + configCacheGrayTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8")); + configCacheGrayTag.setEncryptedDataKey("key_testGetTag_NotDirectRead"); + ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, + TagGrayRule.VERSION, specificTag, -999); + configCacheGrayTag.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo)); + cacheItem.sortConfigGray(); //specific tag to get - String specificTag = "specific_tag"; - //just for compare. - cacheItem.getConfigCacheTags().put(specificTag, configCacheTag); when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem); ConfigQueryRequest configQueryRequest = new ConfigQueryRequest(); @@ -251,7 +260,8 @@ void testGetTagWithTag() throws Exception { requestMeta.setClientIp("127.0.0.1"); //mock disk read. - when(configRocksDbDiskService.getTagContent(eq(dataId), eq(group), eq(null), eq(specificTag))).thenReturn(tagContent); + when(configRocksDbDiskService.getGrayContent(eq(dataId), eq(group), eq(null), + eq(TagGrayRule.TYPE_TAG + "_" + specificTag))).thenReturn(tagContent); ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta); //check content&md5 @@ -277,28 +287,31 @@ void testGetTagAutoTag() throws Exception { ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class); when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService); + String autoTag = "auto_tag"; CacheItem cacheItem = new CacheItem(groupKey); + cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + "_" + autoTag); cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); - ConfigCache configCacheTag = new ConfigCache(); + ConfigCacheGray configCacheGrayTag = cacheItem.getConfigCacheGray().get(TagGrayRule.TYPE_TAG + "_" + autoTag); String tagContent = "content_from_specific_tag_directreadÄãºÃ" + System.currentTimeMillis(); - configCacheTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK")); - configCacheTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8")); - configCacheTag.setEncryptedDataKey("key_testGetTag_AutoTag_NotDirectRead"); - cacheItem.initConfigTagsIfEmpty(); - String autoTag = "auto_tag"; - cacheItem.getConfigCacheTags().put(autoTag, configCacheTag); + configCacheGrayTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK")); + configCacheGrayTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8")); + configCacheGrayTag.setEncryptedDataKey("key_testGetTag_AutoTag_NotDirectRead"); + ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, + TagGrayRule.VERSION, autoTag, -999); + configCacheGrayTag.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo)); + cacheItem.sortConfigGray(); when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem); ConfigQueryRequest configQueryRequest = new ConfigQueryRequest(); configQueryRequest.setDataId(dataId); configQueryRequest.setGroup(group); - configQueryRequest.putHeader(VIPSERVER_TAG, autoTag); RequestMeta requestMeta = new RequestMeta(); requestMeta.setClientIp("127.0.0.1"); - + requestMeta.getAppLabels().put(VIPSERVER_TAG, autoTag); //mock disk read. - when(configRocksDbDiskService.getTagContent(eq(dataId), eq(group), eq(null), eq(autoTag))).thenReturn(tagContent); + when(configRocksDbDiskService.getGrayContent(eq(dataId), eq(group), eq(null), + eq(TagGrayRule.TYPE_TAG + "_" + autoTag))).thenReturn(tagContent); ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta); //check content&md5 @@ -324,8 +337,8 @@ void testGetConfigNotExistAndConflict() throws Exception { String group = "group" + System.currentTimeMillis(); String tenant = "tenant" + System.currentTimeMillis(); //test config not exist - configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))) - .thenReturn(0); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(0); final String groupKey = GroupKey2.getKey(dataId, group, tenant); when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(null); @@ -345,8 +358,8 @@ void testGetConfigNotExistAndConflict() throws Exception { //test config conflict when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(new CacheItem(groupKey)); - configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))) - .thenReturn(-1); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(-1); ConfigQueryResponse responseConflict = configQueryRequestHandler.handle(configQueryRequest, requestMeta); assertEquals(ConfigQueryResponse.CONFIG_QUERY_CONFLICT, responseConflict.getErrorCode()); assertNull(responseConflict.getContent()); diff --git a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandlerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandlerTest.java index f489b112a83..8d05297ccff 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandlerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandlerTest.java @@ -21,8 +21,8 @@ import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.remote.request.RequestMeta; import com.alibaba.nacos.api.remote.response.ResponseCode; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.trace.ConfigTraceService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -43,11 +43,12 @@ class ConfigRemoveRequestHandlerTest { private ConfigInfoPersistService configInfoPersistService; @Mock - private ConfigInfoTagPersistService configInfoTagPersistService; + private ConfigInfoGrayPersistService configInfoGrayPersistService; @BeforeEach void setUp() throws Exception { - configRemoveRequestHandler = new ConfigRemoveRequestHandler(configInfoPersistService, configInfoTagPersistService); + configRemoveRequestHandler = new ConfigRemoveRequestHandler(configInfoPersistService, + configInfoGrayPersistService); Mockito.mockStatic(ConfigTraceService.class); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/remote/RpcConfigChangeNotifierTest.java b/config/src/test/java/com/alibaba/nacos/config/server/remote/RpcConfigChangeNotifierTest.java index 98e0806b46f..a838db8d737 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/remote/RpcConfigChangeNotifierTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/remote/RpcConfigChangeNotifierTest.java @@ -131,7 +131,7 @@ void testOnDataEvent() throws InterruptedException { //mock push tps passed Mockito.when(tpsControlManager.check(any(TpsCheckRequest.class))).thenReturn(new TpsCheckResponse(true, 200, "success")); - rpcConfigChangeNotifier.onEvent(new LocalDataChangeEvent(groupKey, true, betaIps)); + rpcConfigChangeNotifier.onEvent(new LocalDataChangeEvent(groupKey)); //wait rpc push executed. Thread.sleep(50L); //expect rpc push task run. diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/AggrWhitelistTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/AggrWhitelistTest.java deleted file mode 100644 index dbda0ad4bf9..00000000000 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/AggrWhitelistTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service; - -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class AggrWhitelistTest { - - @Test - void testIsAggrDataId() { - List list = new ArrayList(); - list.add("com.taobao.jiuren.*"); - list.add("NS_NACOS_SUBSCRIPTION_TOPIC_*"); - list.add("com.taobao.tae.AppListOnGrid-*"); - AggrWhitelist.compile(list); - - assertFalse(AggrWhitelist.isAggrDataId("com.abc")); - assertFalse(AggrWhitelist.isAggrDataId("com.taobao.jiuren")); - assertFalse(AggrWhitelist.isAggrDataId("com.taobao.jiurenABC")); - assertTrue(AggrWhitelist.isAggrDataId("com.taobao.jiuren.abc")); - assertTrue(AggrWhitelist.isAggrDataId("NS_NACOS_SUBSCRIPTION_TOPIC_abc")); - assertTrue(AggrWhitelist.isAggrDataId("com.taobao.tae.AppListOnGrid-abc")); - } -} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java index fccdb2e5b90..b23610b1e1b 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java @@ -18,7 +18,8 @@ import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.config.server.model.CacheItem; -import com.alibaba.nacos.config.server.model.ConfigCache; +import com.alibaba.nacos.config.server.model.ConfigCacheGray; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; import com.alibaba.nacos.config.server.utils.GroupKey2; @@ -37,8 +38,6 @@ import java.io.IOException; import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -67,7 +66,8 @@ class ConfigCacheServiceTest { void before() { envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class); - configDiskServiceFactoryMockedStatic.when(() -> ConfigDiskServiceFactory.getInstance()).thenReturn(configDiskService); + configDiskServiceFactoryMockedStatic.when(() -> ConfigDiskServiceFactory.getInstance()) + .thenReturn(configDiskService); propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class); } @@ -92,7 +92,8 @@ void testDumpFormal() throws Exception { long ts = System.currentTimeMillis(); String type = "json"; String encryptedDataKey = "key12345"; - boolean result = ConfigCacheService.dumpWithMd5(dataId, group, tenant, content, md5, ts, type, encryptedDataKey); + boolean result = ConfigCacheService.dumpWithMd5(dataId, group, tenant, content, md5, ts, type, + encryptedDataKey); assertTrue(result); //verify cache. CacheItem contentCache1 = ConfigCacheService.getContentCache(groupKey); @@ -132,7 +133,8 @@ void testDumpFormal() throws Exception { .saveToDisk(anyString(), anyString(), anyString(), anyString()); try { long newTs3 = newTs2 + 123L; - boolean dumpErrorResult = ConfigCacheService.dump(dataId, group, tenant, contentNew + "234567", newTs3, type, encryptedDataKey); + boolean dumpErrorResult = ConfigCacheService.dump(dataId, group, tenant, contentNew + "234567", newTs3, + type, encryptedDataKey); envUtilMockedStatic.verify(() -> EnvUtil.systemExit(), times(1)); assertFalse(dumpErrorResult); } catch (Throwable throwable) { @@ -149,163 +151,100 @@ void testDumpFormal() throws Exception { } @Test - void testDumpBeta() throws Exception { + public void testDumpGray() throws Exception { String dataId = "dataIdtestDumpBetaNewCache123"; String group = "group11"; String tenant = "tenant112"; - String content = "mockContnet11"; + String grayName = "grayName"; + String grayRule = "{\"type\":\"tag\",\"version\":\"1.0.0\",\"expr\":\"dgray123\",\"priority\":1}"; + String content = "mockContent11"; + String md5 = MD5Utils.md5Hex(content, "UTF-8"); String groupKey = GroupKey2.getKey(dataId, group, tenant); String encryptedDataKey = "key12345"; - List betaIps = Arrays.asList("127.0.0.1", "127.0.0.2"); long ts = System.currentTimeMillis(); - //init beta cache - boolean result = ConfigCacheService.dumpBeta(dataId, group, tenant, content, ts, String.join(",", betaIps), encryptedDataKey); + //init gray cache + boolean result = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, content, ts, + encryptedDataKey); assertTrue(result); CacheItem contentCache = ConfigCacheService.getContentCache(groupKey); - assertEquals(md5, contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(ts, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertEquals(betaIps, contentCache.getIps4Beta()); - assertEquals(encryptedDataKey, contentCache.getConfigCacheBeta().getEncryptedDataKey()); - Mockito.verify(configDiskService, times(1)).saveBetaToDisk(eq(dataId), eq(group), eq(tenant), eq(content)); + assertEquals(md5, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(ts, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); + assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); + Mockito.verify(configDiskService, times(1)) + .saveGrayToDisk(eq(dataId), eq(group), eq(tenant), eq(grayName), eq(content)); //ts newer ,md5 update long tsNew = System.currentTimeMillis(); String contentNew = content + tsNew; String md5New = MD5Utils.md5Hex(contentNew, "UTF-8"); - List betaIpsNew = Arrays.asList("127.0.0.1", "127.0.0.2", "127.0.0.3"); - boolean resultNew = ConfigCacheService.dumpBeta(dataId, group, tenant, contentNew, tsNew, String.join(",", betaIpsNew), + boolean resultNew = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, contentNew, tsNew, encryptedDataKey); assertTrue(resultNew); - assertEquals(md5New, contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(tsNew, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertEquals(encryptedDataKey, contentCache.getConfigCacheBeta().getEncryptedDataKey()); - assertEquals(betaIpsNew, contentCache.getIps4Beta()); - Mockito.verify(configDiskService, times(1)).saveBetaToDisk(eq(dataId), eq(group), eq(tenant), eq(contentNew)); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(tsNew, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); + assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); + Mockito.verify(configDiskService, times(1)) + .saveGrayToDisk(eq(dataId), eq(group), eq(tenant), eq(grayName), eq(contentNew)); //ts old ,md5 update long tsOld = tsNew - 1; String contentWithOldTs = "contentWithOldTs" + tsOld; - List betaIpsWithOldTs = Arrays.asList("127.0.0.1", "127.0.0.2", "127.0.0.4"); - boolean resultOld = ConfigCacheService.dumpBeta(dataId, group, tenant, contentWithOldTs, tsOld, String.join(",", betaIpsWithOldTs), - encryptedDataKey); + boolean resultOld = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, contentWithOldTs, + tsOld, encryptedDataKey); assertTrue(resultOld); - assertEquals(md5New, contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(tsNew, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertEquals(encryptedDataKey, contentCache.getConfigCacheBeta().getEncryptedDataKey()); - assertEquals(betaIpsNew, contentCache.getIps4Beta()); - Mockito.verify(configDiskService, times(0)).saveBetaToDisk(eq(dataId), eq(group), eq(tenant), eq(contentWithOldTs)); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(tsNew, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); + assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); + Mockito.verify(configDiskService, times(0)) + .saveGrayToDisk(eq(dataId), eq(group), eq(tenant), eq(grayName), eq(contentWithOldTs)); - //ts new ,md5 not update,beta ips list changes + //ts new ,md5 not update,grayRule changes long tsNew2 = tsNew + 1; + String grayRuleNew = "{\"type\":\"tag\",\"version\":\"1.0.0\",\"expr\":\"gray1234\",\"priority\":1}"; + String contentWithPrev = contentNew; - List betaIpsNew2 = Arrays.asList("127.0.0.1", "127.0.0.2", "127.0.0.4", "127.0.0.5"); - boolean resultNew2 = ConfigCacheService.dumpBeta(dataId, group, tenant, contentWithPrev, tsNew2, String.join(",", betaIpsNew2), - encryptedDataKey); + boolean resultNew2 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRuleNew, contentWithPrev, + tsNew2, encryptedDataKey); assertTrue(resultNew2); - assertEquals(md5New, contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(tsNew2, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertEquals(encryptedDataKey, contentCache.getConfigCacheBeta().getEncryptedDataKey()); - assertEquals(betaIpsNew2, contentCache.getIps4Beta()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(tsNew2, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); + assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); + assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)), + contentCache.getConfigCacheGray().get(grayName).getGrayRule()); //ts new only,md5 not update,beta ips not change long tsNew3 = tsNew2 + 1; String contentWithPrev2 = contentNew; - List betaIpsNew3 = betaIpsNew2; - boolean resultNew3 = ConfigCacheService.dumpBeta(dataId, group, tenant, contentWithPrev2, tsNew3, String.join(",", betaIpsNew3), - encryptedDataKey); + String grayRulePrev = grayRuleNew; + boolean resultNew3 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRulePrev, + contentWithPrev2, tsNew3, encryptedDataKey); assertTrue(resultNew3); - assertEquals(md5New, contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(tsNew3, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertEquals(encryptedDataKey, contentCache.getConfigCacheBeta().getEncryptedDataKey()); - assertEquals(betaIpsNew2, contentCache.getIps4Beta()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(tsNew3, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); + assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); + assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)), + contentCache.getConfigCacheGray().get(grayName).getGrayRule()); //ts not update,md5 not update,beta ips not change long tsNew4 = tsNew3; String contentWithPrev4 = contentNew; - List betaIpsNew4 = betaIpsNew2; - boolean resultNew4 = ConfigCacheService.dumpBeta(dataId, group, tenant, contentWithPrev4, tsNew4, String.join(",", betaIpsNew4), - encryptedDataKey); + boolean resultNew4 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRulePrev, + contentWithPrev4, tsNew4, encryptedDataKey); assertTrue(resultNew4); - assertEquals(md5New, contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(tsNew3, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertEquals(encryptedDataKey, contentCache.getConfigCacheBeta().getEncryptedDataKey()); - assertEquals(betaIpsNew4, contentCache.getIps4Beta()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(tsNew3, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); + assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); + assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)), + contentCache.getConfigCacheGray().get(grayName).getGrayRule()); //test remove - boolean removeBeta = ConfigCacheService.removeBeta(dataId, group, tenant); + boolean removeBeta = ConfigCacheService.removeGray(dataId, group, tenant, grayName); assertTrue(removeBeta); - Mockito.verify(configDiskService, times(1)).removeConfigInfo4Beta(dataId, group, tenant); - ConfigCache betaCacheAfterRemove = ConfigCacheService.getContentCache(groupKey).getConfigCacheBeta(); - assertNull(betaCacheAfterRemove); - } - - @Test - void testDumpTag() throws Exception { - String dataId = "dataIdtestDumpTag133323"; - String group = "group11"; - String tenant = "tenant112"; - String content = "mockContnet11"; - String tag = "tag12345"; - String groupKey = GroupKey2.getKey(dataId, group, tenant); - String encryptedDataKey = "key12345"; - long ts = System.currentTimeMillis(); - - //init dump tag - boolean dumpTagResult = ConfigCacheService.dumpTag(dataId, group, tenant, tag, content, ts, encryptedDataKey); - assertTrue(dumpTagResult); - Mockito.verify(configDiskService, times(1)).saveTagToDisk(eq(dataId), eq(group), eq(tenant), eq(tag), eq(content)); - CacheItem contentCache = ConfigCacheService.getContentCache(groupKey); - ConfigCache configCacheTag = contentCache.getConfigCacheTags().get(tag); - assertEquals(ts, configCacheTag.getLastModifiedTs()); - String md5 = MD5Utils.md5Hex(content, "UTF-8"); - assertEquals(md5, configCacheTag.getMd5Utf8()); - - //ts newer ,md5 update - long tsNew = System.currentTimeMillis(); - String contentNew = content + tsNew; - String md5New = MD5Utils.md5Hex(contentNew, "UTF-8"); - boolean resultNew = ConfigCacheService.dumpTag(dataId, group, tenant, tag, contentNew, tsNew, encryptedDataKey); - assertTrue(resultNew); - assertEquals(md5New, configCacheTag.getMd5Utf8()); - assertEquals(tsNew, configCacheTag.getLastModifiedTs()); - assertEquals(encryptedDataKey, configCacheTag.getEncryptedDataKey()); - Mockito.verify(configDiskService, times(1)).saveTagToDisk(eq(dataId), eq(group), eq(tenant), eq(tag), eq(contentNew)); - - //ts old ,md5 update - long tsOld = tsNew - 1; - String contentWithOldTs = "contentWithOldTs" + tsOld; - boolean resultOld = ConfigCacheService.dumpTag(dataId, group, tenant, tag, contentWithOldTs, tsOld, encryptedDataKey); - assertTrue(resultOld); - assertEquals(md5New, configCacheTag.getMd5Utf8()); - assertEquals(tsNew, configCacheTag.getLastModifiedTs()); - assertEquals(encryptedDataKey, configCacheTag.getEncryptedDataKey()); - Mockito.verify(configDiskService, times(0)).saveTagToDisk(eq(dataId), eq(group), eq(tenant), eq(tag), eq(contentWithOldTs)); - - //ts new only,md5 not update - long tsNew2 = tsNew + 1; - String contentWithPrev2 = contentNew; - boolean resultNew2 = ConfigCacheService.dumpTag(dataId, group, tenant, tag, contentWithPrev2, tsNew2, encryptedDataKey); - assertTrue(resultNew2); - assertEquals(md5New, configCacheTag.getMd5Utf8()); - assertEquals(tsNew2, configCacheTag.getLastModifiedTs()); - assertEquals(encryptedDataKey, configCacheTag.getEncryptedDataKey()); - - //ts not update,md5 not update - long tsNew3 = tsNew2; - String contentWithPrev3 = contentNew; - boolean resultNew3 = ConfigCacheService.dumpTag(dataId, group, tenant, tag, contentWithPrev3, tsNew3, encryptedDataKey); - assertTrue(resultNew3); - assertEquals(md5New, configCacheTag.getMd5Utf8()); - assertEquals(tsNew3, configCacheTag.getLastModifiedTs()); - assertEquals(encryptedDataKey, configCacheTag.getEncryptedDataKey()); - - //test remove - boolean removeTag = ConfigCacheService.removeTag(dataId, group, tenant, tag); - assertTrue(removeTag); - Mockito.verify(configDiskService, times(1)).removeConfigInfo4Tag(dataId, group, tenant, tag); - Map configCacheTags = ConfigCacheService.getContentCache(groupKey).getConfigCacheTags(); - assertNull(configCacheTags); + Mockito.verify(configDiskService, times(1)).removeConfigInfo4Gray(dataId, group, tenant, grayName); + Map grayCacheAfterRemove = ConfigCacheService.getContentCache(groupKey) + .getConfigCacheGray(); + assertNull(grayCacheAfterRemove); } @Test diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigChangePublisherTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigChangePublisherTest.java index 79f4e065631..aaa0aaebd1a 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigChangePublisherTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigChangePublisherTest.java @@ -62,7 +62,8 @@ public Class subscribeType() { EnvUtil.setIsStandalone(true); DatasourceConfiguration.setEmbeddedStorage(true); - ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); + ConfigChangePublisher.notifyConfigChange( + new ConfigDataChangeEvent("chuntaojun", "chuntaojun", null, System.currentTimeMillis())); Thread.sleep(2000); assertNotNull(reference.get()); reference.set(null); @@ -70,7 +71,8 @@ public Class subscribeType() { // nacos is standalone mode and use external storage EnvUtil.setIsStandalone(true); DatasourceConfiguration.setEmbeddedStorage(false); - ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); + ConfigChangePublisher.notifyConfigChange( + new ConfigDataChangeEvent("chuntaojun", "chuntaojun", null, System.currentTimeMillis())); Thread.sleep(2000); assertNotNull(reference.get()); reference.set(null); @@ -78,7 +80,8 @@ public Class subscribeType() { // nacos is cluster mode and use embedded storage EnvUtil.setIsStandalone(false); DatasourceConfiguration.setEmbeddedStorage(true); - ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); + ConfigChangePublisher.notifyConfigChange( + new ConfigDataChangeEvent("chuntaojun", "chuntaojun", null, System.currentTimeMillis())); Thread.sleep(2000); assertNull(reference.get()); reference.set(null); @@ -86,7 +89,8 @@ public Class subscribeType() { // nacos is cluster mode and use external storage EnvUtil.setIsStandalone(false); DatasourceConfiguration.setEmbeddedStorage(false); - ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent("chuntaojun", "chuntaojun", System.currentTimeMillis())); + ConfigChangePublisher.notifyConfigChange( + new ConfigDataChangeEvent("chuntaojun", "chuntaojun", null, System.currentTimeMillis())); Thread.sleep(2000); assertNotNull(reference.get()); reference.set(null); diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigOperationServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigOperationServiceTest.java index 7451b7214dc..48414cd2098 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigOperationServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigOperationServiceTest.java @@ -22,6 +22,7 @@ import com.alibaba.nacos.config.server.model.ConfigRequestInfo; import com.alibaba.nacos.config.server.model.form.ConfigForm; import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.sys.env.EnvUtil; @@ -34,6 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,15 +61,18 @@ class ConfigOperationServiceTest { @Mock private ConfigInfoBetaPersistService configInfoBetaPersistService; + @Mock + private ConfigInfoGrayPersistService configInfoGrayPersistService; + @BeforeEach void setUp() throws Exception { EnvUtil.setEnvironment(new StandardEnvironment()); this.configOperationService = new ConfigOperationService(configInfoPersistService, configInfoTagPersistService, - configInfoBetaPersistService); + configInfoBetaPersistService, configInfoGrayPersistService); } @Test - void testPublishConfig() throws NacosException { + void testPublishConfigBeta() throws NacosException { ConfigForm configForm = new ConfigForm(); configForm.setDataId("test"); configForm.setGroup("test"); @@ -75,55 +80,115 @@ void testPublishConfig() throws NacosException { ConfigRequestInfo configRequestInfo = new ConfigRequestInfo(); - // if betaIps is blank, tag is blank and casMd5 is blank - when(configInfoPersistService.insertOrUpdate(any(), any(), any(ConfigInfo.class), any())).thenReturn(new ConfigOperateResult()); - Boolean aResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); - verify(configInfoPersistService).insertOrUpdate(any(), any(), any(ConfigInfo.class), any()); - assertTrue(aResult); + configRequestInfo.setCasMd5(""); + configForm.setTag(""); - // if betaIps is blank, tag is blank and casMd5 is not blank + // if betaIps is not blank and casMd5 is blank + configRequestInfo.setBetaIps("test-betaIps"); + when(configInfoBetaPersistService.insertOrUpdateBeta(any(ConfigInfo.class), eq("test-betaIps"), any(), + any())).thenReturn(new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq("beta"), anyString(), + eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult()); + Boolean eResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); + verify(configInfoBetaPersistService).insertOrUpdateBeta(any(ConfigInfo.class), eq("test-betaIps"), any(), + any()); + assertTrue(eResult); + + } + + @Test + void testPublishConfigBetaCas() throws NacosException { + ConfigForm configForm = new ConfigForm(); + configForm.setDataId("test"); + configForm.setGroup("test"); + configForm.setContent("test content"); + + ConfigRequestInfo configRequestInfo = new ConfigRequestInfo(); + + configRequestInfo.setCasMd5("casMd5"); + configForm.setTag(""); + + // if betaIps is not blank and casMd5 is not blank + configRequestInfo.setBetaIps("test-betaIps"); configRequestInfo.setCasMd5("test casMd5"); - when(configInfoPersistService.insertOrUpdateCas(any(), any(), any(ConfigInfo.class), any())).thenReturn(new ConfigOperateResult()); - Boolean bResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); - verify(configInfoPersistService).insertOrUpdateCas(any(), any(), any(ConfigInfo.class), any()); - assertTrue(bResult); + when(configInfoBetaPersistService.insertOrUpdateBetaCas(any(ConfigInfo.class), eq("test-betaIps"), any(), + any())).thenReturn(new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq("beta"), anyString(), + eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult()); + Boolean fResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); + verify(configInfoBetaPersistService).insertOrUpdateBetaCas(any(ConfigInfo.class), eq("test-betaIps"), any(), + any()); + assertTrue(fResult); + } + + @Test + void testPublishConfigTag() throws NacosException { + ConfigForm configForm = new ConfigForm(); + configForm.setDataId("test"); + configForm.setGroup("test"); + configForm.setContent("test content"); + + ConfigRequestInfo configRequestInfo = new ConfigRequestInfo(); + configRequestInfo.setCasMd5(""); + String tag = "testTag"; + configForm.setTag(tag); - // if betaIps is blank, tag is not blank and casMd5 is blank - configForm.setTag("test tag"); - when(configInfoTagPersistService.insertOrUpdateTag(any(ConfigInfo.class), eq("test tag"), any(), any())).thenReturn( + when(configInfoTagPersistService.insertOrUpdateTag(any(ConfigInfo.class), eq(tag), any(), any())).thenReturn( new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq("tag_" + tag), anyString(), + eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult()); Boolean cResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); - verify(configInfoTagPersistService).insertOrUpdateTag(any(ConfigInfo.class), eq("test tag"), any(), any()); + verify(configInfoTagPersistService).insertOrUpdateTag(any(ConfigInfo.class), eq(tag), any(), any()); assertTrue(cResult); - // if betaIps is blank, tag is not blank and casMd5 is not blank - configForm.setTag("test tag"); - configRequestInfo.setCasMd5("test casMd5"); - when(configInfoTagPersistService.insertOrUpdateTagCas(any(ConfigInfo.class), eq("test tag"), any(), any())).thenReturn( + } + + @Test + void testPublishConfigTagCas() throws NacosException { + ConfigForm configForm = new ConfigForm(); + configForm.setDataId("test"); + configForm.setGroup("test"); + configForm.setContent("test content"); + + ConfigRequestInfo configRequestInfo = new ConfigRequestInfo(); + + configRequestInfo.setCasMd5("casMd5"); + String tag = "testTag"; + configForm.setTag(tag); + when(configInfoTagPersistService.insertOrUpdateTagCas(any(ConfigInfo.class), eq(tag), any(), any())).thenReturn( new ConfigOperateResult()); + when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq("tag_" + tag), anyString(), + eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult()); Boolean dResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); - verify(configInfoTagPersistService).insertOrUpdateTagCas(any(ConfigInfo.class), eq("test tag"), any(), any()); + verify(configInfoTagPersistService).insertOrUpdateTagCas(any(ConfigInfo.class), eq(tag), any(), any()); assertTrue(dResult); - configRequestInfo.setCasMd5(""); - configForm.setTag(""); + } + + @Test + void testPublishConfig() throws NacosException { + ConfigForm configForm = new ConfigForm(); + configForm.setDataId("test"); + configForm.setGroup("test"); + configForm.setContent("test content"); - // if betaIps is not blank and casMd5 is blank - configRequestInfo.setBetaIps("test-betaIps"); - when(configInfoBetaPersistService.insertOrUpdateBeta(any(ConfigInfo.class), eq("test-betaIps"), any(), any())).thenReturn( + ConfigRequestInfo configRequestInfo = new ConfigRequestInfo(); + + // if betaIps is blank, tag is blank and casMd5 is blank + when(configInfoPersistService.insertOrUpdate(any(), any(), any(ConfigInfo.class), any())).thenReturn( new ConfigOperateResult()); - Boolean eResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); - verify(configInfoBetaPersistService).insertOrUpdateBeta(any(ConfigInfo.class), eq("test-betaIps"), any(), any()); - assertTrue(eResult); + Boolean aResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); + verify(configInfoPersistService).insertOrUpdate(any(), any(), any(ConfigInfo.class), any()); + assertTrue(aResult); - // if betaIps is not blank and casMd5 is not blank - configRequestInfo.setBetaIps("test-betaIps"); + // if betaIps is blank, tag is blank and casMd5 is not blank configRequestInfo.setCasMd5("test casMd5"); - when(configInfoBetaPersistService.insertOrUpdateBetaCas(any(ConfigInfo.class), eq("test-betaIps"), any(), any())).thenReturn( + when(configInfoPersistService.insertOrUpdateCas(any(), any(), any(ConfigInfo.class), any())).thenReturn( new ConfigOperateResult()); - Boolean fResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); - verify(configInfoBetaPersistService).insertOrUpdateBetaCas(any(ConfigInfo.class), eq("test-betaIps"), any(), any()); - assertTrue(fResult); + Boolean bResult = configOperationService.publishConfig(configForm, configRequestInfo, ""); + verify(configInfoPersistService).insertOrUpdateCas(any(), any(), any(ConfigInfo.class), any()); + assertTrue(bResult); + configRequestInfo.setCasMd5(""); } @Test @@ -136,7 +201,8 @@ void testDeleteConfig() { // if tag is not blank Boolean bResult = configOperationService.deleteConfig("test", "test", "", "test", "1.1.1.1", "test"); - verify(configInfoTagPersistService).removeConfigInfoTag(eq("test"), eq("test"), eq(""), eq("test"), any(), any()); + verify(configInfoTagPersistService).removeConfigInfoTag(eq("test"), eq("test"), eq(""), eq("test"), any(), + any()); assertTrue(bResult); } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java index cde308bce33..614d655c90e 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java @@ -105,8 +105,7 @@ void after() throws IllegalAccessException { dynamicDataSourceMockedStatic.close(); envUtilMockedStatic.close(); ConfigDiskServiceFactory.getInstance().clearAll(); - ConfigDiskServiceFactory.getInstance().clearAllBeta(); - ConfigDiskServiceFactory.getInstance().clearAllTag(); + ConfigDiskServiceFactory.getInstance().clearAllGray(); Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields(); for (Field filed : declaredFields) { @@ -121,7 +120,7 @@ void after() throws IllegalAccessException { void testDumpChangeIfOff() { PropertyUtil.setDumpChangeOn(false); dumpChangeConfigWorker.run(); - Mockito.verify(historyConfigInfoPersistService, times(0)).findDeletedConfig(any(), anyLong(), anyInt()); + Mockito.verify(historyConfigInfoPersistService, times(0)).findDeletedConfig(any(), anyLong(), anyInt(), any()); } @Test @@ -141,7 +140,7 @@ void testDumpChangeOfDeleteConfigs() { assertEquals("encrykey" + 1, ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, "group" + 1, "tenant" + 1)).getConfigCache() .getEncryptedDataKey()); - Mockito.when(historyConfigInfoPersistService.findDeletedConfig(eq(startTime), eq(0L), eq(3))).thenReturn(firstPageDeleted); + Mockito.when(historyConfigInfoPersistService.findDeletedConfig(eq(startTime), eq(0L), eq(3), eq("formal"))).thenReturn(firstPageDeleted); //mock delete config query is null Mockito.when(configInfoPersistService.findConfigInfoState(eq(dataIdPrefix + 1), eq("group" + 1), eq("tenant" + 1))) .thenReturn(null); @@ -150,7 +149,7 @@ void testDumpChangeOfDeleteConfigs() { dumpChangeConfigWorker.run(); //expect delete page return pagesize and will select second page - Mockito.verify(historyConfigInfoPersistService, times(1)).findDeletedConfig(eq(startTime), eq(3L), eq(3)); + Mockito.verify(historyConfigInfoPersistService, times(1)).findDeletedConfig(eq(startTime), eq(3L), eq(3), eq("formal")); //expect cache to be cleared. assertNull(ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, "group" + 1, "tenant" + 1))); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorkerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorkerTest.java new file mode 100644 index 00000000000..f1f825241e5 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorkerTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.dump; + +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.service.ConfigCacheService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; +import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.utils.ConfigExecutor; +import com.alibaba.nacos.config.server.utils.GroupKey; +import com.alibaba.nacos.config.server.utils.PropertyUtil; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class DumpChangeGrayConfigWorkerTest { + + DumpChangeGrayConfigWorker dumpGrayConfigWorker; + + @Mock + ConfigInfoGrayPersistService configInfoGrayPersistService; + + @Mock + HistoryConfigInfoPersistService historyConfigInfoPersistService; + + static MockedStatic envUtilMockedStatic; + + static MockedStatic configCacheServiceMockedStatic; + + static MockedStatic configExecutorMockedStatic; + + + /** + * Clean up. + */ + @AfterEach + public void after() { + envUtilMockedStatic.close(); + configCacheServiceMockedStatic.close(); + configExecutorMockedStatic.close(); + + } + + @BeforeEach + public void setUp() { + envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); + configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class); + configExecutorMockedStatic = Mockito.mockStatic(ConfigExecutor.class); + + envUtilMockedStatic.when(() -> EnvUtil.getAvailableProcessors(anyInt())).thenReturn(2); + dumpGrayConfigWorker = new DumpChangeGrayConfigWorker(configInfoGrayPersistService, + new Timestamp(System.currentTimeMillis()), historyConfigInfoPersistService); + } + + @Test + public void testdumpGrayConfigWorkerRun() { + List mockList = new ArrayList<>(); + ConfigInfoGrayWrapper mock1 = mock(1); + mockList.add(mock1); + when(configInfoGrayPersistService.findChangeConfig(any(Timestamp.class), any(long.class), eq(100))).thenReturn( + mockList); + configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentMd5( + eq(GroupKey.getKeyTenant(mock1.getDataId(), mock1.getGroup(), mock1.getTenant())))).thenReturn(""); + + dumpGrayConfigWorker.run(); + //verify dump gray executed + configCacheServiceMockedStatic.verify( + () -> ConfigCacheService.dumpGray(eq(mock1.getDataId()), eq(mock1.getGroup()), eq(mock1.getTenant()), + eq(mock1.getGrayName()), eq(mock1.getGrayRule()), eq(mock1.getContent()), + eq(mock1.getLastModified()), eq(mock1.getEncryptedDataKey()))); + //verify task scheduled + configExecutorMockedStatic.verify(() -> ConfigExecutor.scheduleConfigChangeTask(any(DumpChangeGrayConfigWorker.class), + eq(PropertyUtil.getDumpChangeWorkerInterval()), eq(TimeUnit.MILLISECONDS))); + + } + + ConfigInfoGrayWrapper mock(int id) { + ConfigInfoGrayWrapper configInfoGrayWrapper = new ConfigInfoGrayWrapper(); + configInfoGrayWrapper.setDataId("mockdataid" + id); + configInfoGrayWrapper.setGroup("mockgroup" + id); + configInfoGrayWrapper.setTenant("tenant" + id); + configInfoGrayWrapper.setContent("content" + id); + configInfoGrayWrapper.setGrayName("graytags1" + id); + configInfoGrayWrapper.setGrayRule( + "{\"type\":\"tagv2\",\"version\":\"1.0.0\",\"expr\":\"middleware.server.key\\u003dgray123\",\"priority\":1}"); + return configInfoGrayWrapper; + } +} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java index d01fc330d12..819063612a7 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java @@ -18,8 +18,6 @@ import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.config.server.model.CacheItem; -import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper; -import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoWrapper; import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService; @@ -27,9 +25,8 @@ import com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService; import com.alibaba.nacos.config.server.service.dump.processor.DumpProcessor; import com.alibaba.nacos.config.server.service.dump.task.DumpTask; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.persistence.datasource.DataSourceService; import com.alibaba.nacos.persistence.datasource.DynamicDataSource; @@ -46,7 +43,6 @@ import java.io.IOException; import java.lang.reflect.Field; -import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -67,10 +63,7 @@ class DumpProcessorTest { ConfigInfoPersistService configInfoPersistService; @Mock - ConfigInfoBetaPersistService configInfoBetaPersistService; - - @Mock - ConfigInfoTagPersistService configInfoTagPersistService; + ConfigInfoGrayPersistService configInfoGrayPersistService; ExternalDumpService dumpService; @@ -85,14 +78,18 @@ void init() throws Exception { dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class); envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); when(EnvUtil.getNacosHome()).thenReturn(System.getProperty("user.home")); - when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class), eq(false))).thenReturn(false); + when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class), + eq(false))).thenReturn(false); + when(EnvUtil.getProperty(eq("memory_limit_file_path"), + eq("/sys/fs/cgroup/memory/memory.limit_in_bytes"))).thenReturn( + "/sys/fs/cgroup/memory/memory.limit_in_bytes"); + dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dynamicDataSource); when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService); - dumpService = new ExternalDumpService(configInfoPersistService, null, null, null, configInfoBetaPersistService, - configInfoTagPersistService, null, null); - dumpProcessor = new DumpProcessor(configInfoPersistService, configInfoBetaPersistService, configInfoTagPersistService); + dumpService = new ExternalDumpService(configInfoPersistService, null, null, configInfoGrayPersistService, null); + dumpProcessor = new DumpProcessor(configInfoPersistService, configInfoGrayPersistService); Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields(); for (Field filed : declaredFields) { if (filed.getName().equals("configDiskService")) { @@ -112,8 +109,7 @@ void after() { dynamicDataSourceMockedStatic.close(); envUtilMockedStatic.close(); ConfigDiskServiceFactory.getInstance().clearAll(); - ConfigDiskServiceFactory.getInstance().clearAllBeta(); - ConfigDiskServiceFactory.getInstance().clearAllTag(); + ConfigDiskServiceFactory.getInstance().clearAllGray(); } @@ -131,11 +127,12 @@ void testDumpNormalAndRemove() throws IOException { configInfoWrapper.setContent(content); configInfoWrapper.setLastModified(time); - Mockito.when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(tenant))).thenReturn(configInfoWrapper); + Mockito.when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(tenant))) + .thenReturn(configInfoWrapper); String handlerIp = "127.0.0.1"; long lastModified = System.currentTimeMillis(); - DumpTask dumpTask = new DumpTask(GroupKey2.getKey(dataId, group, tenant), false, false, false, null, lastModified, handlerIp); + DumpTask dumpTask = new DumpTask(GroupKey2.getKey(dataId, group, tenant), null, lastModified, handlerIp); boolean process = dumpProcessor.process(dumpTask); assertTrue(process); @@ -161,98 +158,4 @@ void testDumpNormalAndRemove() throws IOException { assertNull(contentFromDiskAfterRemove); } - - @Test - void testDumpBetaAndRemove() throws IOException { - String dataId = "testDataIdBeta"; - String group = "testGroup"; - String tenant = "testTenant"; - String content = "testContentBeta你好" + System.currentTimeMillis(); - long time = System.currentTimeMillis(); - ConfigInfoBetaWrapper configInfoWrapper = new ConfigInfoBetaWrapper(); - configInfoWrapper.setDataId(dataId); - configInfoWrapper.setGroup(group); - configInfoWrapper.setTenant(tenant); - configInfoWrapper.setContent(content); - configInfoWrapper.setLastModified(time); - String betaIps = "127.0.0.1123,127.0.0.11"; - configInfoWrapper.setBetaIps(betaIps); - - Mockito.when(configInfoBetaPersistService.findConfigInfo4Beta(eq(dataId), eq(group), eq(tenant))).thenReturn(configInfoWrapper); - - String handlerIp = "127.0.0.1"; - long lastModified = System.currentTimeMillis(); - DumpTask dumpTask = new DumpTask(GroupKey2.getKey(dataId, group, tenant), true, false, false, null, lastModified, handlerIp); - boolean process = dumpProcessor.process(dumpTask); - assertTrue(process); - - //Check cache - CacheItem contentCache = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)); - assertEquals(MD5Utils.md5Hex(content, "UTF-8"), contentCache.getConfigCacheBeta().getMd5Utf8()); - assertEquals(time, contentCache.getConfigCacheBeta().getLastModifiedTs()); - assertTrue(contentCache.ips4Beta.containsAll(Arrays.asList(betaIps.split(",")))); - //check disk - String contentFromDisk = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant); - assertEquals(content, contentFromDisk); - - // remove - Mockito.when(configInfoBetaPersistService.findConfigInfo4Beta(eq(dataId), eq(group), eq(tenant))).thenReturn(null); - boolean processRemove = dumpProcessor.process(dumpTask); - assertTrue(processRemove); - - //Check cache - CacheItem contentCacheAfterRemove = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)); - assertTrue(contentCacheAfterRemove == null || contentCacheAfterRemove.getConfigCacheBeta() == null); - //check disk - String contentFromDiskAfterRemove = ConfigDiskServiceFactory.getInstance().getBetaContent(dataId, group, tenant); - assertNull(contentFromDiskAfterRemove); - - } - - @Test - void testDumpTagAndRemove() throws IOException { - String dataId = "testDataIdBeta"; - String group = "testGroup"; - String tenant = "testTenant"; - String tag = "testTag111"; - String content = "testContentBeta你好" + System.currentTimeMillis(); - long time = System.currentTimeMillis(); - ConfigInfoTagWrapper configInfoWrapper = new ConfigInfoTagWrapper(); - configInfoWrapper.setDataId(dataId); - configInfoWrapper.setGroup(group); - configInfoWrapper.setTenant(tenant); - configInfoWrapper.setContent(content); - configInfoWrapper.setLastModified(time); - configInfoWrapper.setTag(tag); - Mockito.when(configInfoTagPersistService.findConfigInfo4Tag(eq(dataId), eq(group), eq(tenant), eq(tag))) - .thenReturn(configInfoWrapper); - - String handlerIp = "127.0.0.1"; - long lastModified = System.currentTimeMillis(); - DumpTask dumpTask = new DumpTask(GroupKey2.getKey(dataId, group, tenant), false, false, true, tag, lastModified, handlerIp); - boolean process = dumpProcessor.process(dumpTask); - assertTrue(process); - - //Check cache - CacheItem contentCache = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)); - assertEquals(MD5Utils.md5Hex(content, "UTF-8"), contentCache.getConfigCacheTags().get(tag).getMd5Utf8()); - assertEquals(time, contentCache.getConfigCacheTags().get(tag).getLastModifiedTs()); - //check disk - String contentFromDisk = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag); - assertEquals(content, contentFromDisk); - - // remove - Mockito.when(configInfoTagPersistService.findConfigInfo4Tag(eq(dataId), eq(group), eq(tenant), eq(tag))).thenReturn(null); - boolean processRemove = dumpProcessor.process(dumpTask); - assertTrue(processRemove); - - //Check cache - CacheItem contentCacheAfterRemove = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)); - assertTrue(contentCacheAfterRemove == null || contentCache.getConfigCacheTags() == null - || contentCache.getConfigCacheTags().get(tag) == null); - //check disk - String contentFromDiskAfterRemove = ConfigDiskServiceFactory.getInstance().getTagContent(dataId, group, tenant, tag); - assertNull(contentFromDiskAfterRemove); - - } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorUserRwaDiskTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorUserRwaDiskTest.java index 27a3bf09fc9..41f464686ce 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorUserRwaDiskTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorUserRwaDiskTest.java @@ -49,14 +49,4 @@ public void testDumpNormalAndRemove() throws IOException { super.testDumpNormalAndRemove(); } - - @Test - public void testDumpBetaAndRemove() throws IOException { - super.testDumpBetaAndRemove(); - } - - @Test - public void testDumpTagAndRemove() throws IOException { - super.testDumpTagAndRemove(); - } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpServiceTest.java index 884561422d1..850a42bc11f 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpServiceTest.java @@ -17,14 +17,10 @@ package com.alibaba.nacos.config.server.service.dump; import com.alibaba.nacos.config.server.manager.TaskManager; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; import com.alibaba.nacos.config.server.service.dump.task.DumpTask; -import com.alibaba.nacos.config.server.service.merge.MergeDatumService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.config.server.utils.ConfigExecutor; import com.alibaba.nacos.config.server.utils.GroupKey; @@ -44,14 +40,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.util.ReflectionTestUtils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.concurrent.TimeUnit; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -78,16 +70,7 @@ class DumpServiceTest { HistoryConfigInfoPersistService historyConfigInfoPersistService; @Mock - ConfigInfoAggrPersistService configInfoAggrPersistService; - - @Mock - ConfigInfoBetaPersistService configInfoBetaPersistService; - - @Mock - ConfigInfoTagPersistService configInfoTagPersistService; - - @Mock - MergeDatumService mergeDatumService; + ConfigInfoGrayPersistService configInfoGrayPersistService; @Mock ServerMemberManager memberManager; @@ -117,11 +100,12 @@ void setUp() { ReflectionTestUtils.setField(DynamicDataSource.getInstance(), "localDataSourceService", dataSourceService); ReflectionTestUtils.setField(DynamicDataSource.getInstance(), "basicDataSourceService", dataSourceService); - dumpService = new ExternalDumpService(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService, - configInfoAggrPersistService, configInfoBetaPersistService, configInfoTagPersistService, mergeDatumService, memberManager); + dumpService = new ExternalDumpService(configInfoPersistService, namespacePersistService, + historyConfigInfoPersistService, configInfoGrayPersistService, memberManager); configExecutorMocked = Mockito.mockStatic(ConfigExecutor.class); historyConfigCleanerManagerMockedStatic = Mockito.mockStatic(HistoryConfigCleanerManager.class); - historyConfigCleanerManagerMockedStatic.when(() -> HistoryConfigCleanerManager.getHistoryConfigCleaner(anyString())) + historyConfigCleanerManagerMockedStatic.when( + () -> HistoryConfigCleanerManager.getHistoryConfigCleaner(anyString())) .thenReturn(defaultHistoryConfigCleaner); } @@ -138,106 +122,80 @@ void after() { void dumpRequest() throws Throwable { String dataId = "12345667dataId"; String group = "234445group"; - DumpRequest dumpRequest = DumpRequest.create(dataId, group, "testtenant", System.currentTimeMillis(), "127.0.0.1"); + DumpRequest dumpRequest = DumpRequest.create(dataId, group, "testtenant", System.currentTimeMillis(), + "127.0.0.1"); // TaskManager dumpTaskMgr; ReflectionTestUtils.setField(dumpService, "dumpTaskMgr", dumpTaskMgr); Mockito.doNothing().when(dumpTaskMgr).addTask(any(), any()); dumpService.dump(dumpRequest); Mockito.verify(dumpTaskMgr, times(1)) .addTask(eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant())), any(DumpTask.class)); - dumpRequest.setBeta(true); - dumpService.dump(dumpRequest); - Mockito.verify(dumpTaskMgr, times(1)) - .addTask(eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant()) + "+beta"), any(DumpTask.class)); - dumpRequest.setBeta(false); - dumpRequest.setBatch(true); - dumpService.dump(dumpRequest); - Mockito.verify(dumpTaskMgr, times(1)) - .addTask(eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant()) + "+batch"), any(DumpTask.class)); - dumpRequest.setBatch(false); - dumpRequest.setTag("testTag111"); + + dumpRequest.setGrayName("tag_123"); dumpService.dump(dumpRequest); - Mockito.verify(dumpTaskMgr, times(1)) - .addTask(eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant()) + "+tag+" + dumpRequest.getTag()), - any(DumpTask.class)); + Mockito.verify(dumpTaskMgr, times(1)).addTask( + eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant()) + "+gray+" + + dumpRequest.getGrayName()), any(DumpTask.class)); } @Test void dumpOperate() throws Throwable { - configExecutorMocked.when(() -> ConfigExecutor.scheduleConfigTask(any(Runnable.class), anyInt(), anyInt(), any(TimeUnit.class))) + configExecutorMocked.when( + () -> ConfigExecutor.scheduleConfigTask(any(Runnable.class), anyInt(), anyInt(), any(TimeUnit.class))) .thenAnswer(invocation -> null); - configExecutorMocked.when(() -> ConfigExecutor.scheduleConfigChangeTask(any(Runnable.class), anyInt(), any(TimeUnit.class))) + configExecutorMocked.when( + () -> ConfigExecutor.scheduleConfigChangeTask(any(Runnable.class), anyInt(), any(TimeUnit.class))) .thenAnswer(invocation -> null); Mockito.when(namespacePersistService.isExistTable(BETA_TABLE_NAME)).thenReturn(true); Mockito.when(namespacePersistService.isExistTable(TAG_TABLE_NAME)).thenReturn(true); - ConfigInfoChanged hasDatum = new ConfigInfoChanged(); - hasDatum.setDataId("hasDatumdataId1"); - hasDatum.setTenant("tenant1"); - hasDatum.setGroup("group1"); - ConfigInfoChanged noDatum = new ConfigInfoChanged(); - noDatum.setDataId("dataId1"); - noDatum.setTenant("tenant1"); - noDatum.setGroup("group1"); - List configList = configInfoAggrPersistService.findAllAggrGroup(); - configList.add(hasDatum); - configList.add(noDatum); - Mockito.when(configInfoAggrPersistService.findAllAggrGroup()).thenReturn(configList); - List> result = new ArrayList<>(); - result.add(Arrays.asList(hasDatum)); - result.add(Arrays.asList(noDatum)); - Mockito.when(mergeDatumService.splitList(anyList(), anyInt())).thenReturn(result); - Mockito.doNothing().when(mergeDatumService).executeConfigsMerge(anyList()); + Mockito.when(configInfoPersistService.findConfigMaxId()).thenReturn(300L); dumpService.dumpOperate(); // expect dump Mockito.verify(configInfoPersistService, times(1)).findAllConfigInfoFragment(0, 100, true); Mockito.verify(configInfoPersistService, times(1)).findConfigMaxId(); - Mockito.verify(configInfoBetaPersistService, times(1)).configInfoBetaCount(); - Mockito.verify(configInfoTagPersistService, times(1)).configInfoTagCount(); - - Mockito.verify(mergeDatumService, times(2)).executeConfigsMerge(anyList()); + Mockito.verify(configInfoGrayPersistService, times(1)).configInfoGrayCount(); // expect dump formal,beta,tag,history clear,config change task to be scheduled. // expect config clear history task be scheduled. configExecutorMocked.verify( - () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllProcessorRunner.class), anyLong(), anyLong(), - eq(TimeUnit.MINUTES)), times(1)); - configExecutorMocked.verify( - () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllBetaProcessorRunner.class), anyLong(), anyLong(), - eq(TimeUnit.MINUTES)), times(1)); + () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllProcessorRunner.class), anyLong(), + anyLong(), eq(TimeUnit.MINUTES)), times(1)); + configExecutorMocked.verify( - () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllTagProcessorRunner.class), anyLong(), anyLong(), - eq(TimeUnit.MINUTES)), times(1)); + () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllGrayProcessorRunner.class), anyLong(), + anyLong(), eq(TimeUnit.MINUTES)), times(1)); configExecutorMocked.verify( - () -> ConfigExecutor.scheduleConfigChangeTask(any(DumpChangeConfigWorker.class), anyLong(), eq(TimeUnit.MILLISECONDS)), - times(1)); + () -> ConfigExecutor.scheduleConfigChangeTask(any(DumpChangeConfigWorker.class), anyLong(), + eq(TimeUnit.MILLISECONDS)), times(1)); configExecutorMocked.verify( () -> ConfigExecutor.scheduleConfigTask(any(DumpService.ConfigHistoryClear.class), anyLong(), anyLong(), - eq(TimeUnit.MINUTES)), times(1) - ); + eq(TimeUnit.MINUTES)), times(1)); } @Test void clearHistory() { envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq("nacos.config.retention.days"))).thenReturn("10"); Mockito.when(memberManager.isFirstIp()).thenReturn(true); - DumpService.ConfigHistoryClear configHistoryClear = dumpService.new ConfigHistoryClear(defaultHistoryConfigCleaner); + DumpService.ConfigHistoryClear configHistoryClear = dumpService.new ConfigHistoryClear( + defaultHistoryConfigCleaner); configHistoryClear.run(); Mockito.verify(defaultHistoryConfigCleaner, times(1)).cleanHistoryConfig(); } @Test void testHandleConfigDataChange() { - ConfigDataChangeEvent configDataChangeEvent = new ConfigDataChangeEvent("dataId", "group", System.currentTimeMillis()); + ConfigDataChangeEvent configDataChangeEvent = new ConfigDataChangeEvent("dataId", "group", null, + System.currentTimeMillis()); ReflectionTestUtils.setField(dumpService, "dumpTaskMgr", dumpTaskMgr); Mockito.doNothing().when(dumpTaskMgr).addTask(any(), any()); dumpService.handleConfigDataChange(configDataChangeEvent); - Mockito.verify(dumpTaskMgr, times(1)) - .addTask(eq(GroupKey.getKeyTenant(configDataChangeEvent.dataId, configDataChangeEvent.group, configDataChangeEvent.tenant)), - any(DumpTask.class)); + Mockito.verify(dumpTaskMgr, times(1)).addTask( + eq(GroupKey.getKeyTenant(configDataChangeEvent.dataId, configDataChangeEvent.group, + configDataChangeEvent.tenant)), any(DumpTask.class)); } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskServiceTest.java index cf01eb366c0..bec451631bd 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskServiceTest.java @@ -75,73 +75,27 @@ void testTargetFileWithInvalidParam() { * 测试获取beta文件路径. */ @Test - void testTargetBetaFile() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method method = ConfigRawDiskService.class.getDeclaredMethod("targetBetaFile", String.class, String.class, - String.class); + void testTargetGrayFile() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Method method = ConfigRawDiskService.class.getDeclaredMethod("targetGrayFile", String.class, String.class, + String.class, String.class); method.setAccessible(true); - File result = (File) method.invoke(null, "aaaa-dsaknkf", "aaaa.dsaknkf", "aaaa:dsaknkf"); + File result = (File) method.invoke(null, "data345678", "group3456", "tenant1234", "graynem4567"); // 分解路径 Path path = Paths.get(result.getPath()); Path parent = path.getParent(); Path grandParent = parent.getParent(); + Path grand2Parent = grandParent.getParent(); + // 获取最后三段路径 - String lastSegment = path.getFileName().toString(); - String secondLastSegment = parent.getFileName().toString(); + String fourthLastSegment = grand2Parent.getFileName().toString(); + assertEquals(fourthLastSegment, "tenant1234"); String thirdLastSegment = grandParent.getFileName().toString(); - assertEquals(isWindows() ? "aaaa-dsaknkf" : thirdLastSegment, thirdLastSegment); - assertEquals(isWindows() ? "aaaa.dsaknkf" : secondLastSegment, secondLastSegment); - assertEquals(isWindows() ? "aaaa%A5%dsaknkf" : lastSegment, lastSegment); - } - - @Test - void testTargetBetaFileWithInvalidParam() throws NoSuchMethodException { - Method method = ConfigRawDiskService.class.getDeclaredMethod("targetBetaFile", String.class, String.class, - String.class); - method.setAccessible(true); - assertThrows(InvocationTargetException.class, () -> method.invoke(null, "../aaa", "testG", "testNS")); - assertThrows(InvocationTargetException.class, () -> method.invoke(null, "testD", "../aaa", "testNS")); - assertThrows(InvocationTargetException.class, () -> method.invoke(null, "testD", "testG", "../aaa")); - } - - /** - * 测试获取tag文件路径. - * - * @throws NoSuchMethodException 方法不存在异常 - * @throws IllegalAccessException 非法访问异常 - * @throws InvocationTargetException 目标异常 - */ - @Test - void testTargetTagFile() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method method = ConfigRawDiskService.class.getDeclaredMethod("targetTagFile", String.class, String.class, - String.class, String.class); - method.setAccessible(true); - File result = (File) method.invoke(null, "aaaa-dsaknkf", "aaaa.dsaknkf", "aaaa:dsaknkf", "aaaa_dsaknkf"); - // 分解路径 - Path path = Paths.get(result.getPath()); - Path parent = path.getParent(); - Path grandParent = parent.getParent(); - Path greatGrandParent = grandParent.getParent(); - // 获取最后四段路径 + assertEquals(isWindows() ? "aaaa-dsaknkf" : thirdLastSegment, "group3456"); String secondLastSegment = parent.getFileName().toString(); - String thirdLastSegment = grandParent.getFileName().toString(); - String fourthLastSegment = greatGrandParent.getFileName().toString(); - assertEquals(isWindows() ? "aaaa-dsaknkf" : fourthLastSegment, fourthLastSegment); - assertEquals(isWindows() ? "aaaa.dsaknkf" : thirdLastSegment, thirdLastSegment); - assertEquals(isWindows() ? "aaaa%A5%dsaknkf" : secondLastSegment, secondLastSegment); + assertEquals(isWindows() ? "aaaa-dsaknkf" : secondLastSegment, "data345678"); String lastSegment = path.getFileName().toString(); - assertEquals("aaaa_dsaknkf", lastSegment); + assertEquals(isWindows() ? "aaaa-dsaknkf" : lastSegment, "graynem4567"); + } - @Test - void testTargetTagFileWithInvalidParam() throws NoSuchMethodException { - Method method = ConfigRawDiskService.class.getDeclaredMethod("targetTagFile", String.class, String.class, - String.class, String.class); - method.setAccessible(true); - assertThrows(InvocationTargetException.class, - () -> method.invoke(null, "../aaa", "testG", "testNS", "testTag")); - assertThrows(InvocationTargetException.class, - () -> method.invoke(null, "testD", "../aaa", "testNS", "testTag")); - assertThrows(InvocationTargetException.class, () -> method.invoke(null, "testD", "testG", "../aaa", "testTag")); - assertThrows(InvocationTargetException.class, () -> method.invoke(null, "testD", "testG", "testNS", "../aaa")); - } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java index 206d950adcf..b765d3a2e72 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java @@ -23,9 +23,8 @@ import com.alibaba.nacos.config.server.service.dump.ExternalDumpService; import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory; import com.alibaba.nacos.config.server.service.dump.task.DumpAllTask; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService; +import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService; import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; import com.alibaba.nacos.config.server.utils.GroupKey2; import com.alibaba.nacos.config.server.utils.PropertyUtil; import com.alibaba.nacos.persistence.datasource.DataSourceService; @@ -63,10 +62,7 @@ class DumpAllProcessorTest { DataSourceService dataSourceService; @Mock - ConfigInfoBetaPersistService configInfoBetaPersistService; - - @Mock - ConfigInfoTagPersistService configInfoTagPersistService; + ConfigInfoGrayPersistService configInfoGrayPersistService; DumpAllProcessor dumpAllProcessor; @@ -92,8 +88,7 @@ void init() throws Exception { when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService); - dumpService = new ExternalDumpService(configInfoPersistService, null, null, null, configInfoBetaPersistService, - configInfoTagPersistService, null, null); + dumpService = new ExternalDumpService(configInfoPersistService, null, null, configInfoGrayPersistService, null); dumpAllProcessor = new DumpAllProcessor(configInfoPersistService); envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq("memory_limit_file_path"), eq("/sys/fs/cgroup/memory/memory.limit_in_bytes"))) diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/merge/MergeDatumServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/merge/MergeDatumServiceTest.java deleted file mode 100644 index f2eeeb570d4..00000000000 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/merge/MergeDatumServiceTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 1999-2023 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.merge; - -import com.alibaba.nacos.config.server.manager.TaskManager; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; -import com.alibaba.nacos.consistency.cp.CPProtocol; -import com.alibaba.nacos.core.distributed.ProtocolManager; -import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration; -import com.alibaba.nacos.persistence.datasource.DataSourceService; -import com.alibaba.nacos.persistence.datasource.DynamicDataSource; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.sys.env.EnvUtil; -import com.alibaba.nacos.sys.utils.ApplicationUtils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.ArrayList; -import java.util.List; - -import static com.alibaba.nacos.persistence.constants.PersistenceConstant.CONFIG_MODEL_RAFT_GROUP; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.when; - -@ExtendWith(SpringExtension.class) -class MergeDatumServiceTest { - - @Mock - ConfigInfoPersistService configInfoPersistService; - - @Mock - ConfigInfoAggrPersistService configInfoAggrPersistService; - - @Mock - ConfigInfoTagPersistService configInfoTagPersistService; - - @Mock - ProtocolManager protocolManager; - - MockedStatic envUtilMockedStatic; - - MockedStatic applicationUtilsMockedStaticc; - - @Mock - private DataSourceService dataSourceService; - - private MergeDatumService mergeDatumService; - - @BeforeEach - void setUp() { - envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); - applicationUtilsMockedStaticc = Mockito.mockStatic(ApplicationUtils.class); - applicationUtilsMockedStaticc.when(() -> ApplicationUtils.getBean(eq(ProtocolManager.class))).thenReturn(protocolManager); - - ReflectionTestUtils.setField(DynamicDataSource.getInstance(), "localDataSourceService", dataSourceService); - ReflectionTestUtils.setField(DynamicDataSource.getInstance(), "basicDataSourceService", dataSourceService); - mergeDatumService = new MergeDatumService(configInfoPersistService, configInfoAggrPersistService, configInfoTagPersistService); - - } - - @AfterEach - void after() { - envUtilMockedStatic.close(); - applicationUtilsMockedStaticc.close(); - } - - @Test - void testSplitList() { - String dataId = "dataID"; - int count = 5; - List configList = new ArrayList<>(); - configList.add(create(dataId, 0)); - configList.add(create(dataId, 1)); - configList.add(create(dataId, 2)); - configList.add(create(dataId, 3)); - configList.add(create(dataId, 4)); - configList.add(create(dataId, 5)); - configList.add(create(dataId, 6)); - configList.add(create(dataId, 7)); - configList.add(create(dataId, 8)); - - List> lists = mergeDatumService.splitList(configList, count); - int originalCount = configList.size(); - int actualCount = 0; - for (int i = 0; i < lists.size(); i++) { - List indexList = lists.get(i); - for (int j = 0; j < indexList.size(); j++) { - ConfigInfoChanged configInfoChanged = indexList.get(j); - actualCount++; - assertEquals(configInfoChanged, configList.get((j * count) + i)); - } - } - - assertEquals(originalCount, actualCount); - - } - - private ConfigInfoChanged create(String dataID, int i) { - ConfigInfoChanged hasDatum = new ConfigInfoChanged(); - hasDatum.setDataId(dataID + i); - hasDatum.setTenant("tenant1"); - hasDatum.setGroup("group1"); - return hasDatum; - } - - @Test - void executeMergeConfigTask() { - envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq("nacos.config.retention.days"))).thenReturn("10"); - ConfigInfoChanged hasDatum = new ConfigInfoChanged(); - hasDatum.setDataId("hasDatumdataId1"); - hasDatum.setTenant("tenant1"); - hasDatum.setGroup("group1"); - ConfigInfoChanged noDatum = new ConfigInfoChanged(); - noDatum.setDataId("dataId1"); - noDatum.setTenant("tenant1"); - noDatum.setGroup("group1"); - List configInfoList = new ArrayList<>(); - configInfoList.add(hasDatum); - configInfoList.add(noDatum); - - when(configInfoAggrPersistService.aggrConfigInfoCount(eq(hasDatum.getDataId()), eq(hasDatum.getGroup()), - eq(hasDatum.getTenant()))).thenReturn(2); - Page datumPage = new Page<>(); - ConfigInfoAggr configInfoAggr1 = new ConfigInfoAggr(); - configInfoAggr1.setContent("12344"); - ConfigInfoAggr configInfoAggr2 = new ConfigInfoAggr(); - configInfoAggr2.setContent("12345666"); - datumPage.getPageItems().add(configInfoAggr1); - datumPage.getPageItems().add(configInfoAggr2); - - when(configInfoAggrPersistService.findConfigInfoAggrByPage(eq(hasDatum.getDataId()), eq(hasDatum.getGroup()), - eq(hasDatum.getTenant()), anyInt(), anyInt())).thenReturn(datumPage); - - when(configInfoAggrPersistService.aggrConfigInfoCount(eq(noDatum.getDataId()), eq(noDatum.getGroup()), - eq(noDatum.getTenant()))).thenReturn(0); - - mergeDatumService.executeMergeConfigTask(configInfoList, 1000); - } - - @Test - void testAddMergeTaskExternalModel() { - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - String clientIp = "127.0.0.1"; - DatasourceConfiguration.setEmbeddedStorage(false); - TaskManager mockTasker = Mockito.mock(TaskManager.class); - ReflectionTestUtils.setField(mergeDatumService, "mergeTasks", mockTasker); - mergeDatumService.addMergeTask(dataId, group, tenant, clientIp); - Mockito.verify(mockTasker, times(1)).addTask(anyString(), any(MergeDataTask.class)); - } - - @Test - void testAddMergeTaskEmbeddedAndStandAloneModel() { - - DatasourceConfiguration.setEmbeddedStorage(true); - envUtilMockedStatic.when(() -> EnvUtil.getStandaloneMode()).thenReturn(true); - TaskManager mockTasker = Mockito.mock(TaskManager.class); - ReflectionTestUtils.setField(mergeDatumService, "mergeTasks", mockTasker); - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - String clientIp = "127.0.0.1"; - mergeDatumService.addMergeTask(dataId, group, tenant, clientIp); - Mockito.verify(mockTasker, times(1)).addTask(anyString(), any(MergeDataTask.class)); - } - - @Test - void testAddMergeTaskEmbeddedAndClusterModelLeader() { - - DatasourceConfiguration.setEmbeddedStorage(true); - envUtilMockedStatic.when(() -> EnvUtil.getStandaloneMode()).thenReturn(false); - TaskManager mockTasker = Mockito.mock(TaskManager.class); - ReflectionTestUtils.setField(mergeDatumService, "mergeTasks", mockTasker); - //mock is leader - CPProtocol cpProtocol = Mockito.mock(CPProtocol.class); - when(protocolManager.getCpProtocol()).thenReturn(cpProtocol); - when(cpProtocol.isLeader(eq(CONFIG_MODEL_RAFT_GROUP))).thenReturn(true); - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - String clientIp = "127.0.0.1"; - mergeDatumService.addMergeTask(dataId, group, tenant, clientIp); - Mockito.verify(mockTasker, times(1)).addTask(anyString(), any(MergeDataTask.class)); - } - - @Test - void testAddMergeTaskEmbeddedAndClusterModelNotLeader() { - - DatasourceConfiguration.setEmbeddedStorage(true); - envUtilMockedStatic.when(() -> EnvUtil.getStandaloneMode()).thenReturn(false); - TaskManager mockTasker = Mockito.mock(TaskManager.class); - ReflectionTestUtils.setField(mergeDatumService, "mergeTasks", mockTasker); - //mock not leader - CPProtocol cpProtocol = Mockito.mock(CPProtocol.class); - when(protocolManager.getCpProtocol()).thenReturn(cpProtocol); - when(cpProtocol.isLeader(eq(CONFIG_MODEL_RAFT_GROUP))).thenReturn(false); - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - String clientIp = "127.0.0.1"; - mergeDatumService.addMergeTask(dataId, group, tenant, clientIp); - Mockito.verify(mockTasker, times(0)).addTask(anyString(), any(MergeDataTask.class)); - } -} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessorTest.java deleted file mode 100644 index 12855d8ff61..00000000000 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/merge/MergeTaskProcessorTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 1999-2023 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.merge; - -import com.alibaba.nacos.common.notify.Event; -import com.alibaba.nacos.common.notify.NotifyCenter; -import com.alibaba.nacos.common.notify.listener.Subscriber; -import com.alibaba.nacos.config.server.model.ConfigInfo; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigOperateResult; -import com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService; -import com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService; -import com.alibaba.nacos.persistence.datasource.DataSourceService; -import com.alibaba.nacos.persistence.datasource.DynamicDataSource; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.sys.env.EnvUtil; -import com.alibaba.nacos.sys.utils.InetUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.concurrent.atomic.AtomicReference; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.when; - -@ExtendWith(SpringExtension.class) - -public class MergeTaskProcessorTest { - - @Mock - ConfigInfoPersistService configInfoPersistService; - - @Mock - ConfigInfoAggrPersistService configInfoAggrPersistService; - - @Mock - ConfigInfoTagPersistService configInfoTagPersistService; - - MockedStatic envUtilMockedStatic; - - MergeTaskProcessor mergeTaskProcessor; - - MockedStatic inetUtilsMockedStatic; - - @Mock - private DataSourceService dataSourceService; - - @Mock - private MergeDatumService mergeDatumService; - - @BeforeEach - void setUp() { - envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); - inetUtilsMockedStatic = Mockito.mockStatic(InetUtils.class); - ReflectionTestUtils.setField(DynamicDataSource.getInstance(), "localDataSourceService", dataSourceService); - ReflectionTestUtils.setField(DynamicDataSource.getInstance(), "basicDataSourceService", dataSourceService); - mergeTaskProcessor = new MergeTaskProcessor(configInfoPersistService, configInfoAggrPersistService, configInfoTagPersistService, - mergeDatumService); - inetUtilsMockedStatic.when(InetUtils::getSelfIP).thenReturn("127.0.0.1"); - after(); - } - - public void after() { - envUtilMockedStatic.close(); - inetUtilsMockedStatic.close(); - } - - /** - * test aggr has datum and merge it expect: 1.config to be inserted 2.config data change event to be published - */ - @Test - void testMergerExistAggrConfig() throws InterruptedException { - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - when(configInfoAggrPersistService.aggrConfigInfoCount(eq(dataId), eq(group), eq(tenant))).thenReturn(2); - Page datumPage = new Page<>(); - ConfigInfoAggr configInfoAggr1 = new ConfigInfoAggr(); - configInfoAggr1.setContent("12344"); - ConfigInfoAggr configInfoAggr2 = new ConfigInfoAggr(); - configInfoAggr2.setContent("12345666"); - datumPage.getPageItems().add(configInfoAggr1); - datumPage.getPageItems().add(configInfoAggr2); - - when(configInfoAggrPersistService.findConfigInfoAggrByPage(eq(dataId), eq(group), eq(tenant), anyInt(), anyInt())).thenReturn( - datumPage); - - when(configInfoPersistService.insertOrUpdate(eq(null), eq(null), any(ConfigInfo.class), eq(null))).thenReturn( - new ConfigOperateResult()); - - AtomicReference reference = new AtomicReference<>(); - NotifyCenter.registerSubscriber(new Subscriber() { - - @Override - public void onEvent(Event event) { - ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event; - if (event1.dataId.equals(dataId) && event1.group.equals(group) && tenant.equals(event1.tenant)) { - reference.set((ConfigDataChangeEvent) event); - } - } - - @Override - public Class subscribeType() { - return ConfigDataChangeEvent.class; - } - }); - - MergeDataTask mergeDataTask = new MergeDataTask(dataId, group, tenant, "127.0.0.1"); - mergeTaskProcessor.process(mergeDataTask); - - Mockito.verify(configInfoPersistService, times(1)).insertOrUpdate(eq(null), eq(null), any(ConfigInfo.class), eq(null)); - Thread.sleep(1000L); - assertTrue(reference.get() != null); - - } - - /** - * test aggr has datum and remove it. - */ - @Test - void testMergerNotExistAggrConfig() throws InterruptedException { - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - when(configInfoAggrPersistService.aggrConfigInfoCount(eq(dataId), eq(group), eq(tenant))).thenReturn(0); - - AtomicReference reference = new AtomicReference<>(); - NotifyCenter.registerSubscriber(new Subscriber() { - - @Override - public void onEvent(Event event) { - ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event; - if (event1.dataId.equals(dataId) && event1.group.equals(group) && tenant.equals(event1.tenant)) { - reference.set((ConfigDataChangeEvent) event); - } - } - - @Override - public Class subscribeType() { - return ConfigDataChangeEvent.class; - } - }); - - MergeDataTask mergeDataTask = new MergeDataTask(dataId, group, tenant, "127.0.0.1"); - Mockito.doNothing().when(configInfoPersistService).removeConfigInfo(eq(dataId), eq(group), eq(tenant), eq("127.0.0.1"), eq(null)); - //Mockito.doNothing().when(configInfoTagPersistService).removeConfigInfoTag(eq(dataId), eq(group), eq(tenant),eq(),eq("127.0.0.1"),eq(null)); - mergeTaskProcessor.process(mergeDataTask); - Mockito.verify(configInfoPersistService, times(1)).removeConfigInfo(eq(dataId), eq(group), eq(tenant), eq("127.0.0.1"), eq(null)); - Thread.sleep(1000L); - assertTrue(reference.get() != null); - } - - /** - * test aggr has no datum and remove it tag. - */ - @Test - void testTagMergerNotExistAggrConfig() throws InterruptedException { - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - String tag = "23456789"; - when(configInfoAggrPersistService.aggrConfigInfoCount(eq(dataId), eq(group), eq(tenant))).thenReturn(0); - - AtomicReference reference = new AtomicReference<>(); - NotifyCenter.registerSubscriber(new Subscriber() { - - @Override - public void onEvent(Event event) { - ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event; - if (event1.dataId.equals(dataId) && event1.group.equals(group) && tenant.equals(event1.tenant) && tag.equals(event1.tag)) { - reference.set((ConfigDataChangeEvent) event); - } - } - - @Override - public Class subscribeType() { - return ConfigDataChangeEvent.class; - } - }); - - MergeDataTask mergeDataTask = new MergeDataTask(dataId, group, tenant, tag, "127.0.0.1"); - - Mockito.doNothing().when(configInfoTagPersistService) - .removeConfigInfoTag(eq(dataId), eq(group), eq(tenant), eq(tag), eq("127.0.0.1"), eq(null)); - mergeTaskProcessor.process(mergeDataTask); - Mockito.verify(configInfoTagPersistService, times(1)) - .removeConfigInfoTag(eq(dataId), eq(group), eq(tenant), eq(tag), eq("127.0.0.1"), eq(null)); - Thread.sleep(1000L); - assertTrue(reference.get() != null); - } - - /** - * test aggr has no datum and remove it tag. - */ - @Test - void testTagMergerError() throws InterruptedException { - String dataId = "dataId12345"; - String group = "group123"; - String tenant = "tenant1234"; - when(configInfoAggrPersistService.aggrConfigInfoCount(eq(dataId), eq(group), eq(tenant))).thenThrow(new NullPointerException()); - - MergeDataTask mergeDataTask = new MergeDataTask(dataId, group, tenant, "127.0.0.1"); - - mergeTaskProcessor.process(mergeDataTask); - Mockito.verify(mergeDatumService, times(1)).addMergeTask(eq(dataId), eq(group), eq(tenant), eq("127.0.0.1")); - - } -} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyServiceTest.java index a6072adab3e..c64869934f0 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyServiceTest.java @@ -96,15 +96,16 @@ void testSyncConfigChangeCallback() { ReflectionTestUtils.setField(asyncNotifyService, "configClusterRpcClientProxy", configClusterRpcClientProxy); String dataId = "testDataId" + timeStamp; String group = "testGroup"; - AsyncNotifyService.NotifySingleRpcTask notifySingleRpcTask = new AsyncNotifyService.NotifySingleRpcTask(dataId, group, null, null, - 0, false, false, member1); - configExecutorMocked.when(() -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class))) + AsyncNotifyService.NotifySingleRpcTask notifySingleRpcTask = new AsyncNotifyService.NotifySingleRpcTask(dataId, + group, null, null, 0, member1); + configExecutorMocked.when( + () -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class))) .thenAnswer(invocation -> null); - notifySingleRpcTask.setBatch(true); notifySingleRpcTask.setTag("test"); notifySingleRpcTask.setBeta(false); - AsyncRpcNotifyCallBack asyncRpcNotifyCallBack = new AsyncRpcNotifyCallBack(asyncNotifyService, notifySingleRpcTask); + AsyncRpcNotifyCallBack asyncRpcNotifyCallBack = new AsyncRpcNotifyCallBack(asyncNotifyService, + notifySingleRpcTask); ConfigChangeClusterSyncResponse successResponse = new ConfigChangeClusterSyncResponse(); //1. success response asyncRpcNotifyCallBack.onResponse(successResponse); @@ -116,8 +117,8 @@ void testSyncConfigChangeCallback() { // expect schedule twice fail or exception response. configExecutorMocked.verify( - () -> ConfigExecutor.scheduleAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class), anyLong(), any(TimeUnit.class)), - times(2)); + () -> ConfigExecutor.scheduleAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class), anyLong(), + any(TimeUnit.class)), times(2)); } /** @@ -146,15 +147,18 @@ void testHandleConfigDataChangeEvent() { Mockito.when(serverMemberManager.allMembersWithoutSelf()).thenReturn(memberList); - configExecutorMocked.when(() -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class))) + configExecutorMocked.when( + () -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class))) .thenAnswer(invocation -> null); String dataId = "testDataId" + timeStamp; String group = "testGroup"; AsyncNotifyService asyncNotifyService = new AsyncNotifyService(serverMemberManager); - asyncNotifyService.handleConfigDataChangeEvent(new ConfigDataChangeEvent(dataId, group, System.currentTimeMillis())); + asyncNotifyService.handleConfigDataChangeEvent( + new ConfigDataChangeEvent(dataId, group, null, System.currentTimeMillis())); // expect schedule twice fail or exception response. - configExecutorMocked.verify(() -> ConfigExecutor.executeAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class)), times(1)); + configExecutorMocked.verify(() -> ConfigExecutor.executeAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class)), + times(1)); } @@ -184,8 +188,9 @@ void testExecuteAsyncRpcTask() throws Exception { for (Member member : memberList) { // grpc report data change only - rpcQueue.add(new AsyncNotifyService.NotifySingleRpcTask(dataId, group, null, null, System.currentTimeMillis(), false, false, - member)); + rpcQueue.add( + new AsyncNotifyService.NotifySingleRpcTask(dataId, group, null, null, System.currentTimeMillis(), + member)); } AsyncNotifyService asyncNotifyService = new AsyncNotifyService(serverMemberManager); @@ -195,14 +200,18 @@ void testExecuteAsyncRpcTask() throws Exception { Mockito.when(serverMemberManager.hasMember(eq(member1.getAddress()))).thenReturn(true); Mockito.when(serverMemberManager.hasMember(eq(member2.getAddress()))).thenReturn(true); Mockito.when(serverMemberManager.hasMember(eq(member3.getAddress()))).thenReturn(true); - Mockito.when(serverMemberManager.stateCheck(eq(member1.getAddress()), eq(HEALTHY_CHECK_STATUS))).thenReturn(true); - Mockito.when(serverMemberManager.stateCheck(eq(member2.getAddress()), eq(HEALTHY_CHECK_STATUS))).thenReturn(true); + Mockito.when(serverMemberManager.stateCheck(eq(member1.getAddress()), eq(HEALTHY_CHECK_STATUS))) + .thenReturn(true); + Mockito.when(serverMemberManager.stateCheck(eq(member2.getAddress()), eq(HEALTHY_CHECK_STATUS))) + .thenReturn(true); // mock stateCheck fail before notify member3 - Mockito.when(serverMemberManager.stateCheck(eq(member3.getAddress()), eq(HEALTHY_CHECK_STATUS))).thenReturn(false); + Mockito.when(serverMemberManager.stateCheck(eq(member3.getAddress()), eq(HEALTHY_CHECK_STATUS))) + .thenReturn(false); //mock syncConfigChange exception when notify member2 Mockito.doThrow(new NacosException()).when(configClusterRpcClientProxy) .syncConfigChange(eq(member2), any(ConfigChangeClusterSyncRequest.class), any(RequestCallBack.class)); - configExecutorMocked.when(() -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class))) + configExecutorMocked.when( + () -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class))) .thenAnswer(invocation -> null); asyncNotifyService.executeAsyncRpcTask(rpcQueue); @@ -216,8 +225,8 @@ void testExecuteAsyncRpcTask() throws Exception { //verify scheduleAsyncNotify member2 & member3 in task when syncConfigChange fail configExecutorMocked.verify( - () -> ConfigExecutor.scheduleAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class), anyLong(), any(TimeUnit.class)), - times(2)); + () -> ConfigExecutor.scheduleAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class), anyLong(), + any(TimeUnit.class)), times(2)); } } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjectorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjectorTest.java index 3e93e4f69c4..9a0681d2fee 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjectorTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjectorTest.java @@ -22,10 +22,10 @@ import com.alibaba.nacos.config.server.model.ConfigInfo; import com.alibaba.nacos.config.server.model.ConfigInfo4Beta; import com.alibaba.nacos.config.server.model.ConfigInfo4Tag; -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; import com.alibaba.nacos.config.server.model.ConfigInfoBase; import com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoChanged; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper; import com.alibaba.nacos.config.server.model.ConfigInfoWrapper; @@ -55,8 +55,8 @@ class ConfigRowMapperInjectorTest { @Test void testInit() { ConfigRowMapperInjector configRowMapperInjector = new ConfigRowMapperInjector(); - assertEquals(ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER, - RowMapperManager.getRowMapper(ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER.getClass().getCanonicalName())); + assertEquals(ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER, RowMapperManager.getRowMapper( + ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER.getClass().getCanonicalName())); } @Test @@ -319,26 +319,38 @@ void testConfigInfoBaseRowMapper() throws SQLException { } @Test - void testConfigInfoAggrRowMapper() throws SQLException { + void testConfigInfoGrayRowMapper() throws SQLException { - ConfigInfoAggr preConfig = new ConfigInfoAggr(); + ConfigInfoGrayWrapper preConfig = new ConfigInfoGrayWrapper(); preConfig.setDataId("testDataId"); preConfig.setGroup("group_id11"); preConfig.setContent("content1123434t"); - preConfig.setDatumId("datum4567890"); + preConfig.setGrayName("grayName"); + preConfig.setGrayRule("rule12345"); preConfig.setTenant("tenang34567890"); preConfig.setAppName("app3456789"); + preConfig.setEncryptedDataKey("key12345"); + Timestamp timestamp = Timestamp.valueOf("2024-12-12 12:34:34"); ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class); Mockito.when(resultSet.getString(eq("data_id"))).thenReturn(preConfig.getDataId()); Mockito.when(resultSet.getString(eq("group_id"))).thenReturn(preConfig.getGroup()); Mockito.when(resultSet.getString(eq("tenant_id"))).thenReturn(preConfig.getTenant()); - Mockito.when(resultSet.getString(eq("datum_id"))).thenReturn(preConfig.getDatumId()); + Mockito.when(resultSet.getString(eq("gray_name"))).thenReturn(preConfig.getGrayName()); + Mockito.when(resultSet.getString(eq("app_name"))).thenReturn(preConfig.getAppName()); + + Mockito.when(resultSet.getString(eq("gray_rule"))).thenReturn(preConfig.getGrayRule()); + Mockito.when(resultSet.getTimestamp(eq("gmt_modified"))).thenReturn(timestamp); + Mockito.when(resultSet.getString(eq("content"))).thenReturn(preConfig.getContent()); Mockito.when(resultSet.getString(eq("app"))).thenReturn(preConfig.getAppName()); - ConfigRowMapperInjector.ConfigInfoAggrRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigInfoAggrRowMapper(); + Mockito.when(resultSet.getString(eq("encrypted_data_key"))).thenReturn(preConfig.getEncryptedDataKey()); + + ConfigRowMapperInjector.ConfigInfoGrayWrapperRowMapper configInfoWrapperRowMapper = + new ConfigRowMapperInjector.ConfigInfoGrayWrapperRowMapper(); - ConfigInfoAggr configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10); + ConfigInfoGrayWrapper configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10); assertEquals(preConfig, configInfoWrapper); + assertEquals(timestamp.getTime(), configInfoWrapper.getLastModified()); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImplTest.java deleted file mode 100644 index 33b45b4ade9..00000000000 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImplTest.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.repository.embedded; - -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.persistence.datasource.DataSourceService; -import com.alibaba.nacos.persistence.datasource.DynamicDataSource; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; -import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate; -import com.alibaba.nacos.sys.env.EnvUtil; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_AGGR_ROW_MAPPER; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_CHANGED_ROW_MAPPER; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -/** - * test for embedded config aggr. - * - * @author shiyiyue - */ -@ExtendWith(SpringExtension.class) -class EmbeddedConfigInfoAggrPersistServiceImplTest { - - MockedStatic envUtilMockedStatic; - - MockedStatic embeddedStorageContextHolderMockedStatic; - - MockedStatic dynamicDataSourceMockedStatic; - - @Mock - DynamicDataSource dynamicDataSource; - - @Mock - DatabaseOperate databaseOperate; - - private EmbeddedConfigInfoAggrPersistServiceImpl embededConfigInfoAggrPersistService; - - @Mock - private DataSourceService dataSourceService; - - @BeforeEach - void before() { - embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class); - dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class); - envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); - when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource); - when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService); - when(dataSourceService.getDataSourceType()).thenReturn("derby"); - envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))).thenReturn(false); - embededConfigInfoAggrPersistService = new EmbeddedConfigInfoAggrPersistServiceImpl(databaseOperate); - } - - @AfterEach - void after() { - dynamicDataSourceMockedStatic.close(); - envUtilMockedStatic.close(); - embeddedStorageContextHolderMockedStatic.close(); - } - - @Test - void testAddAggrConfigInfoOfEqualContent() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId and equal with current content param. - String existContent = "content1234"; - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))) - .thenReturn(existContent); - //mock insert success - Mockito.when(databaseOperate.update(any(List.class))).thenReturn(true); - - boolean result = embededConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(result); - } - - @Test - void testAddAggrConfigInfoOfAddNewContent() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId and return null. - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))) - .thenReturn(null); - //mock insert success - Mockito.when(databaseOperate.update(any(List.class))).thenReturn(true); - - //execute - boolean result = embededConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(result); - } - - @Test - void testAddAggrConfigInfoOfUpdateNotEqualContent() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId - String existContent = "existContent111"; - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))) - .thenReturn(existContent); - //mock update success,return 1 - Mockito.when(databaseOperate.update(any(List.class))).thenReturn(true); - - //mock update content - boolean result = embededConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(result); - - } - - @Test - void testBatchPublishAggrSuccess() { - - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - //mock query datumId and equal with current content param. - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, "d1"}), eq(String.class))) - .thenReturn("c1"); - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, "d2"}), eq(String.class))) - .thenReturn("c2"); - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, "d3"}), eq(String.class))) - .thenReturn("c3"); - Mockito.when(databaseOperate.update(any(List.class))).thenReturn(true); - - Map datumMap = new HashMap<>(); - datumMap.put("d1", "c1"); - datumMap.put("d2", "c2"); - datumMap.put("d3", "c3"); - String appName = "appname1234"; - boolean result = embededConfigInfoAggrPersistService.batchPublishAggr(dataId, group, tenant, datumMap, appName); - assertTrue(result); - } - - @Test - void testAggrConfigInfoCount() { - String dataId = "dataId11122"; - String group = "group"; - String tenant = "tenant"; - - //mock select count of aggr. - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class))) - .thenReturn(new Integer(101)); - int result = embededConfigInfoAggrPersistService.aggrConfigInfoCount(dataId, group, tenant); - assertEquals(101, result); - - } - - @Test - void testFindConfigInfoAggrByPage() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - - //mock query count. - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class))).thenReturn(101); - //mock query page list - List configInfoAggrs = new ArrayList<>(); - configInfoAggrs.add(new ConfigInfoAggr()); - configInfoAggrs.add(new ConfigInfoAggr()); - configInfoAggrs.add(new ConfigInfoAggr()); - - Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_AGGR_ROW_MAPPER))) - .thenReturn(configInfoAggrs); - int pageNo = 1; - int pageSize = 120; - Page configInfoAggrByPage = embededConfigInfoAggrPersistService.findConfigInfoAggrByPage(dataId, group, tenant, - pageNo, pageSize); - assertEquals(101, configInfoAggrByPage.getTotalCount()); - assertEquals(configInfoAggrs, configInfoAggrByPage.getPageItems()); - - } - - @Test - void testFindAllAggrGroup() { - List configList = new ArrayList<>(); - configList.add(create("dataId", 0)); - configList.add(create("dataId", 1)); - //mock return list - Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_CHANGED_ROW_MAPPER))) - .thenReturn(configList); - - List allAggrGroup = embededConfigInfoAggrPersistService.findAllAggrGroup(); - assertEquals(configList, allAggrGroup); - - } - - private ConfigInfoChanged create(String dataID, int i) { - ConfigInfoChanged hasDatum = new ConfigInfoChanged(); - hasDatum.setDataId(dataID + i); - hasDatum.setTenant("tenant1"); - hasDatum.setGroup("group1"); - return hasDatum; - } - -} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImplTest.java new file mode 100644 index 00000000000..5d6e05ac9df --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImplTest.java @@ -0,0 +1,422 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.repository.embedded; + +import com.alibaba.nacos.common.utils.MD5Utils; +import com.alibaba.nacos.config.server.constant.Constants; +import com.alibaba.nacos.config.server.model.ConfigInfo; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; +import com.alibaba.nacos.config.server.model.ConfigOperateResult; +import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.core.distributed.id.IdGeneratorManager; +import com.alibaba.nacos.persistence.datasource.DataSourceService; +import com.alibaba.nacos.persistence.datasource.DynamicDataSource; +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; +import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER; +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +/** + * test for embedded config tag. + * + * @author shiyiyue + */ +@ExtendWith(SpringExtension.class) +public class EmbeddedConfigInfoGrayPersistServiceImplTest { + + private EmbeddedConfigInfoGrayPersistServiceImpl embeddedConfigInfoGrayPersistService; + + @Mock + private DataSourceService dataSourceService; + + @Mock + private IdGeneratorManager idGeneratorManager; + + @Mock + private HistoryConfigInfoPersistService historyConfigInfoPersistService; + + MockedStatic envUtilMockedStatic; + + MockedStatic embeddedStorageContextHolderMockedStatic; + + MockedStatic dynamicDataSourceMockedStatic; + + @Mock + DynamicDataSource dynamicDataSource; + + @Mock + DatabaseOperate databaseOperate; + + /** + * before test. + */ + @BeforeEach + public void before() { + embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class); + dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class); + envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); + when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource); + when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService); + when(dataSourceService.getDataSourceType()).thenReturn("derby"); + envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))) + .thenReturn(false); + embeddedConfigInfoGrayPersistService = new EmbeddedConfigInfoGrayPersistServiceImpl(databaseOperate, + idGeneratorManager, historyConfigInfoPersistService); + } + + /** + * after each case. + */ + @AfterEach + public void after() { + dynamicDataSourceMockedStatic.close(); + envUtilMockedStatic.close(); + embeddedStorageContextHolderMockedStatic.close(); + } + + @Test + public void testInsertOrUpdateGrayOfAdd() { + String dataId = "dataId111222"; + String group = "group"; + String tenant = "tenant"; + String appName = "appname1234"; + String content = "c12345"; + + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key23456"); + //mock query config state empty and return obj after insert + ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper(); + configInfoStateWrapper.setLastModified(System.currentTimeMillis()); + configInfoStateWrapper.setId(234567890L); + String grayName = "tag123grayName"; + String grayRule = ""; + + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null).thenReturn(configInfoStateWrapper); + + String srcIp = "ip345678"; + String srcUser = "user1234567"; + ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, + grayName, grayRule, srcIp, srcUser); + + //mock insert invoked. + embeddedStorageContextHolderMockedStatic.verify( + () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), any(), eq(dataId), eq(group), eq(tenant), + eq(grayName), eq(grayRule), eq(appName), eq(content), + eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), + any(Timestamp.class), any(Timestamp.class)), times(1)); + + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic( + eq(configInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I"), + eq("gray"), anyString()); + assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + + } + + @Test + public void testInsertOrUpdateGrayOfUpdate() { + String dataId = "dataId111222"; + String group = "group"; + String tenant = "tenant"; + String appName = "appname1234"; + String content = "c12345"; + + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key23456"); + //mock query config state and return obj after update + ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper(); + configInfoStateWrapper.setLastModified(System.currentTimeMillis()); + configInfoStateWrapper.setId(234567890L); + String grayName = "tag123grayName"; + final String grayRule = "tag123grayrule"; + + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper()) + .thenReturn(configInfoStateWrapper); + + //mock exist config info + ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper(); + configAllInfo4Gray.setDataId(dataId); + configAllInfo4Gray.setGroup(group); + configAllInfo4Gray.setTenant(tenant); + configAllInfo4Gray.setMd5("old_md5"); + configAllInfo4Gray.setSrcUser("user"); + when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray); + + String srcIp = "ip345678"; + String srcUser = "user1234567"; + ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, + grayName, grayRule, srcIp, srcUser); + //verify update to be invoked + embeddedStorageContextHolderMockedStatic.verify( + () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content), + eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), + any(Timestamp.class), eq(appName), eq(grayRule), eq(dataId), eq(group), eq(tenant), + eq(grayName)), times(1)); + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic( + eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("U"), + eq("gray"), anyString()); + assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + + } + + @Test + public void testInsertOrUpdateGrayCasOfAdd() { + String dataId = "dataId111222"; + String group = "group"; + String tenant = "tenant"; + String appName = "appname1234"; + String content = "c12345"; + + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key23456"); + configInfo.setMd5("casMd5"); + //mock query config state empty and return obj after insert + ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper(); + configInfoStateWrapper.setLastModified(System.currentTimeMillis()); + configInfoStateWrapper.setId(234567890L); + String grayName = "tag123grayName"; + String grayRule = ""; + + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null).thenReturn(configInfoStateWrapper); + + String srcIp = "ip345678"; + String srcUser = "user1234567"; + ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, + grayName, grayRule, srcIp, srcUser); + //verify insert to be invoked + //mock insert invoked. + embeddedStorageContextHolderMockedStatic.verify( + () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), any(), eq(dataId), eq(group), eq(tenant), + eq(grayName), eq(grayRule), eq(appName), eq(content), + eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), + any(Timestamp.class), any(Timestamp.class)), times(1)); + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic( + eq(configInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I"), + eq("gray"), anyString()); + assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + + } + + @Test + public void testInsertOrUpdateGrayCasOfUpdate() { + String dataId = "dataId111222"; + String group = "group"; + String tenant = "tenant"; + String appName = "appname1234"; + String content = "c12345"; + + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key23456"); + configInfo.setMd5("casMd5"); + //mock query config state and return obj after update + ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper(); + configInfoStateWrapper.setLastModified(System.currentTimeMillis()); + configInfoStateWrapper.setId(234567890L); + String grayName = "tag123grayName"; + final String grayRule = ""; + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper()) + .thenReturn(configInfoStateWrapper); + + //mock exist config info + ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper(); + configAllInfo4Gray.setDataId(dataId); + configAllInfo4Gray.setGroup(group); + configAllInfo4Gray.setTenant(tenant); + configAllInfo4Gray.setMd5("old_md5"); + configAllInfo4Gray.setSrcUser("user"); + when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray); + + String srcIp = "ip345678"; + String srcUser = "user1234567"; + + //mock cas update return 1 + Mockito.when(databaseOperate.blockUpdate()).thenReturn(true); + ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, + grayName, grayRule, srcIp, srcUser); + //verify update to be invoked + embeddedStorageContextHolderMockedStatic.verify( + () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content), + eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), eq(appName), + eq(grayRule), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(configInfo.getMd5())), + times(1)); + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic( + eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("U"), + eq("gray"), anyString()); + assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + } + + @Test + public void testRemoveConfigInfoGrayName() { + String dataId = "dataId1112222"; + String group = "group22"; + String tenant = "tenant2"; + final String srcIp = "ip345678"; + final String srcUser = "user1234567"; + final String grayName = "grayName..."; + + //mock exist config info + ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper(); + configAllInfo4Gray.setDataId(dataId); + configAllInfo4Gray.setGroup(group); + configAllInfo4Gray.setTenant(tenant); + configAllInfo4Gray.setMd5("old_md5"); + + when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray); + + embeddedConfigInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, grayName, srcIp, srcUser); + + //verify delete sql invoked. + embeddedStorageContextHolderMockedStatic.verify( + () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant), + eq(grayName)), times(1)); + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic( + eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("D"), + eq("gray"), anyString()); + } + + @Test + public void testFindConfigInfo4Gray() { + String dataId = "dataId1112222"; + String group = "group22"; + String tenant = "tenant2"; + String grayName = "tag123345"; + + //mock query tag return obj + ConfigInfoGrayWrapper configInfoGrayWrapperMocked = new ConfigInfoGrayWrapper(); + configInfoGrayWrapperMocked.setLastModified(System.currentTimeMillis()); + + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configInfoGrayWrapperMocked); + + ConfigInfoGrayWrapper configInfo4GrayReturn = embeddedConfigInfoGrayPersistService.findConfigInfo4Gray(dataId, + group, tenant, grayName); + assertEquals(configInfoGrayWrapperMocked, configInfo4GrayReturn); + } + + @Test + public void testConfigInfoGrayCount() { + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + + //mock count + Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(308); + //execute & verify + int count = embeddedConfigInfoGrayPersistService.configInfoGrayCount(); + assertEquals(308, count); + } + + @Test + public void testFindAllConfigInfoGrayForDumpAll() { + + //mock count + Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(308); + List mockGrayList = new ArrayList<>(); + mockGrayList.add(new ConfigInfoGrayWrapper()); + mockGrayList.add(new ConfigInfoGrayWrapper()); + mockGrayList.add(new ConfigInfoGrayWrapper()); + mockGrayList.get(0).setLastModified(System.currentTimeMillis()); + mockGrayList.get(1).setLastModified(System.currentTimeMillis()); + mockGrayList.get(2).setLastModified(System.currentTimeMillis()); + //mock query list + Mockito.when( + databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))) + .thenReturn(mockGrayList); + int pageNo = 3; + int pageSize = 100; + //execute & verify + Page returnGrayPage = embeddedConfigInfoGrayPersistService.findAllConfigInfoGrayForDumpAll( + pageNo, pageSize); + assertEquals(308, returnGrayPage.getTotalCount()); + assertEquals(mockGrayList, returnGrayPage.getPageItems()); + } + + @Test + public void testFindConfigInfoGrays() { + String dataId = "dataId1112222"; + String group = "group22"; + String tenant = "tenant2"; + List mockedGrays = Arrays.asList("tags1", "tags11", "tags111"); + Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}), eq(String.class))) + .thenReturn(mockedGrays); + List configInfoGrays = embeddedConfigInfoGrayPersistService.findConfigInfoGrays(dataId, group, tenant); + assertEquals(mockedGrays, configInfoGrays); + } + + @Test + public void testFindChangeConfigInfo4Gray() { + List mockList = new ArrayList<>(); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.get(0).setLastModified(System.currentTimeMillis()); + mockList.get(1).setLastModified(System.currentTimeMillis()); + mockList.get(2).setLastModified(System.currentTimeMillis()); + long lastMaxId = 123; + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + when(databaseOperate.queryMany(anyString(), eq(new Object[] {timestamp, lastMaxId, 100}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockList) + .thenThrow(new CannotGetJdbcConnectionException("mock exception22")); + + List changeConfig = embeddedConfigInfoGrayPersistService.findChangeConfig(timestamp, + lastMaxId, 100); + assertTrue(changeConfig.get(0).getLastModified() == mockList.get(0).getLastModified()); + assertTrue(changeConfig.get(1).getLastModified() == mockList.get(1).getLastModified()); + assertTrue(changeConfig.get(2).getLastModified() == mockList.get(2).getLastModified()); + try { + embeddedConfigInfoGrayPersistService.findChangeConfig(timestamp, lastMaxId, 100); + assertTrue(false); + } catch (CannotGetJdbcConnectionException exception) { + assertEquals("mock exception22", exception.getMessage()); + } + + } + +} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImplTest.java index b62a44521bb..8fd9c680ae1 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImplTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImplTest.java @@ -16,6 +16,7 @@ package com.alibaba.nacos.config.server.service.repository.embedded; +import com.alibaba.nacos.api.config.ConfigType; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.common.utils.MD5Utils; import com.alibaba.nacos.common.utils.StringUtils; @@ -28,6 +29,7 @@ import com.alibaba.nacos.config.server.model.ConfigOperateResult; import com.alibaba.nacos.config.server.model.SameConfigPolicy; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; import com.alibaba.nacos.core.distributed.id.IdGeneratorManager; import com.alibaba.nacos.persistence.datasource.DataSourceService; import com.alibaba.nacos.persistence.datasource.DynamicDataSource; @@ -153,8 +155,8 @@ void testInsertOrUpdateOfInsertConfigSuccess() { String srcIp = "srcIp"; String srcUser = "srcUser"; //mock insert config info - Mockito.doNothing().when(historyConfigInfoPersistService) - .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + Mockito.doNothing().when(historyConfigInfoPersistService).insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), + any(Timestamp.class), eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); ConfigOperateResult configOperateResult = embeddedConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo); @@ -176,7 +178,8 @@ void testInsertOrUpdateOfInsertConfigSuccess() { //expect insert history info Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I"), + eq("formal"), eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); } @@ -233,7 +236,8 @@ void testInsertOrUpdateCasOfInsertConfigSuccess() { //expect insert history info Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I"), eq("formal"), + eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); } @Test @@ -266,15 +270,15 @@ void testInsertOrUpdateOfUpdateConfigSuccess() { .thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper()); //mock select config info before update - ConfigInfoWrapper configInfoWrapperOld = new ConfigInfoWrapper(); - configInfoWrapperOld.setDataId(dataId); - configInfoWrapperOld.setGroup(group); - configInfoWrapperOld.setTenant(tenant); - configInfoWrapperOld.setAppName("old_app"); - configInfoWrapperOld.setMd5("old_md5"); - configInfoWrapperOld.setId(12345678765L); - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))) - .thenReturn(configInfoWrapperOld); + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_ALL_INFO_ROW_MAPPER))) + .thenReturn(configAllInfo); String srcIp = "srcIp"; String srcUser = "srcUser"; embeddedConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo); @@ -294,8 +298,8 @@ void testInsertOrUpdateOfUpdateConfigSuccess() { //expect insert history info of U Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), - any(Timestamp.class), eq("U")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), + any(Timestamp.class), eq("U"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); } @@ -331,15 +335,16 @@ void testInsertOrUpdateCasOfUpdateConfigSuccess() { .thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper()); //mock select config info before update - ConfigInfoWrapper configInfoWrapperOld = new ConfigInfoWrapper(); - configInfoWrapperOld.setDataId(dataId); - configInfoWrapperOld.setGroup(group); - configInfoWrapperOld.setTenant(tenant); - configInfoWrapperOld.setAppName("old_app11"); - configInfoWrapperOld.setMd5("old_md5"); - configInfoWrapperOld.setId(123456799L); - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))) - .thenReturn(configInfoWrapperOld); + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_ALL_INFO_ROW_MAPPER))) + .thenReturn(configAllInfo); String srcIp = "srcIp"; String srcUser = "srcUser"; @@ -361,8 +366,8 @@ void testInsertOrUpdateCasOfUpdateConfigSuccess() { //expect insert history info of U Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), - any(Timestamp.class), eq("U")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), any(Timestamp.class), + eq("U"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); } @@ -373,17 +378,21 @@ void testRemoveConfigInfo() { String tenant = "tenant4567890"; //mock exist config info - ConfigInfoWrapper configInfoWrapperOld = new ConfigInfoWrapper(); - configInfoWrapperOld.setDataId(dataId); - configInfoWrapperOld.setGroup(group); - configInfoWrapperOld.setTenant(tenant); - configInfoWrapperOld.setAppName("old_app"); - configInfoWrapperOld.setContent("old content"); - configInfoWrapperOld.setMd5("old_md5"); - configInfoWrapperOld.setId(12345678765L); - configInfoWrapperOld.setEncryptedDataKey("key3456"); - Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))) - .thenReturn(configInfoWrapperOld); + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + configAllInfo.setType(ConfigType.JSON.getType()); + configAllInfo.setSchema("testschema"); + configAllInfo.setCreateUser("testuser"); + configAllInfo.setEffect("online"); + configAllInfo.setDesc("desc"); + configAllInfo.setUse("use124"); + Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_ALL_INFO_ROW_MAPPER))) + .thenReturn(configAllInfo); String srcIp = "srcIp1234"; String srcUser = "srcUser"; Mockito.when(databaseOperate.update(any())).thenReturn(true); @@ -394,11 +403,11 @@ void testRemoveConfigInfo() { () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant)), times(1)); //expect delete config tag to be invoked embeddedStorageContextHolderMockedStatic.verify( - () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(configInfoWrapperOld.getId())), times(1)); + () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(configAllInfo.getId())), times(1)); //expect insert delete history Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), eq(configInfoWrapperOld), eq(srcIp), eq(srcUser), any(), - eq("D")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configAllInfo), eq(srcIp), eq(srcUser), any(), + eq("D"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); } @@ -406,13 +415,23 @@ void testRemoveConfigInfo() { void testRemoveConfigInfoByIds() { //mock exist config info - List configInfos = new ArrayList<>(); - configInfos.add(new ConfigInfo("data1", "group", "tenant", "app", "content")); - configInfos.add(new ConfigInfo("data2", "grou2", "tenan2", "app2", "content2")); + final List configAllInfos = new ArrayList<>(); + final ConfigAllInfo configAllInfo1 = new ConfigAllInfo(); + final ConfigAllInfo configAllInfo2 = new ConfigAllInfo(); + configAllInfo1.setDataId("dataId1"); + configAllInfo1.setGroup("group1"); + configAllInfo1.setTenant("tenant1"); + configAllInfo1.setAppName("app1"); + configAllInfo2.setDataId("dataId2"); + configAllInfo2.setGroup("group2"); + configAllInfo2.setTenant("tenant2"); + configAllInfo2.setAppName("app2"); + configAllInfos.add(configAllInfo1); + configAllInfos.add(configAllInfo2); List deleteIds = Arrays.asList(12344L, 3456789L); - configInfos.get(0).setId(12344L); - configInfos.get(1).setId(3456789L); - Mockito.when(databaseOperate.queryMany(anyString(), eq(deleteIds.toArray()), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(configInfos); + configAllInfos.get(0).setId(12344L); + configAllInfos.get(1).setId(3456789L); + Mockito.when(databaseOperate.queryMany(anyString(), eq(deleteIds.toArray()), eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfos); String srcIp = "srcIp1234"; String srcUser = "srcUser"; Mockito.when(databaseOperate.update(any())).thenReturn(true); @@ -430,10 +449,13 @@ void testRemoveConfigInfoByIds() { embeddedStorageContextHolderMockedStatic.verify(() -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(deleteId1)), times(1)); //expect insert delete history + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic(eq(configAllInfos.get(0).getId()), + eq(configAllInfos.get(0)), eq(srcIp), eq(srcUser), any(), eq("D"), eq("formal"), + eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(0)))); Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfos.get(0).getId()), eq(configInfos.get(0)), eq(srcIp), eq(srcUser), any(), eq("D")); - Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfos.get(1).getId()), eq(configInfos.get(1)), eq(srcIp), eq(srcUser), any(), eq("D")); + .insertConfigHistoryAtomic(eq(configAllInfos.get(1).getId()), + eq(configAllInfos.get(1)), eq(srcIp), eq(srcUser), any(), eq("D"), eq("formal"), + eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(1)))); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImplTest.java index 47a33bf16a2..232d6e52038 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImplTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImplTest.java @@ -38,7 +38,6 @@ import java.util.ArrayList; import java.util.List; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -102,16 +101,20 @@ void testInsertConfigHistoryAtomic() { String srcUser = "user12345"; String srcIp = "ip1234"; String ops = "D"; + String publishType = "formal"; + String extraInfo = "{\"type\":\"properties\"}"; Timestamp timestamp = new Timestamp(System.currentTimeMillis()); ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); configInfo.setEncryptedDataKey("key23456"); //expect insert success,verify insert invoked - embeddedHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp, ops); + embeddedHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp, ops, + publishType, extraInfo); //verify insert to be invoked embeddedStorageContextHolderMockedStatic.verify( () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(id), eq(dataId), eq(group), eq(tenant), eq(appName), - eq(content), eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), + eq(content), eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq( + publishType), eq(extraInfo), eq(configInfo.getEncryptedDataKey())), times(1)); } @@ -129,38 +132,40 @@ void testRemoveConfigHistory() { void testFindDeletedConfig() { //mock query list return - ConfigInfoStateWrapper mockObj1 = new ConfigInfoStateWrapper(); + ConfigHistoryInfo mockObj1 = new ConfigHistoryInfo(); mockObj1.setDataId("data_id1"); mockObj1.setGroup("group_id1"); mockObj1.setTenant("tenant_id1"); mockObj1.setMd5("md51"); - mockObj1.setLastModified(System.currentTimeMillis()); + mockObj1.setLastModifiedTime(new Timestamp(System.currentTimeMillis())); - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(mockObj1); - ConfigInfoStateWrapper mockObj2 = new ConfigInfoStateWrapper(); + ConfigHistoryInfo mockObj2 = new ConfigHistoryInfo(); mockObj2.setDataId("data_id2"); mockObj2.setGroup("group_id2"); mockObj2.setTenant("tenant_id2"); mockObj2.setMd5("md52"); + mockObj2.setLastModifiedTime(new Timestamp(System.currentTimeMillis())); list.add(mockObj2); int pageSize = 1233; long startId = 23456; Timestamp timestamp = new Timestamp(System.currentTimeMillis()); - Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {timestamp, startId, pageSize}), - eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(list); + String publishType = "formal"; + Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {publishType, timestamp, startId, pageSize}), + eq(HISTORY_DETAIL_ROW_MAPPER))).thenReturn(list); //execute List deletedConfig = embeddedHistoryConfigInfoPersistService.findDeletedConfig(timestamp, startId, - pageSize); + pageSize, "formal"); //expect verify assertEquals("data_id1", deletedConfig.get(0).getDataId()); assertEquals("group_id1", deletedConfig.get(0).getGroup()); assertEquals("tenant_id1", deletedConfig.get(0).getTenant()); - assertEquals(mockObj1.getLastModified(), deletedConfig.get(0).getLastModified()); + assertEquals(mockObj1.getLastModifiedTime(), new Timestamp(deletedConfig.get(0).getLastModified())); assertEquals("data_id2", deletedConfig.get(1).getDataId()); assertEquals("group_id2", deletedConfig.get(1).getGroup()); assertEquals("tenant_id2", deletedConfig.get(1).getTenant()); - assertEquals(mockObj2.getLastModified(), deletedConfig.get(1).getLastModified()); + assertEquals(mockObj2.getLastModifiedTime(), new Timestamp(deletedConfig.get(1).getLastModified())); } @Test diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImplTest.java deleted file mode 100644 index 93209fb85fa..00000000000 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImplTest.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright 1999-2018 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.config.server.service.repository.extrnal; - -import com.alibaba.nacos.config.server.model.ConfigInfoAggr; -import com.alibaba.nacos.config.server.model.ConfigInfoChanged; -import com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils; -import com.alibaba.nacos.config.server.utils.TestCaseUtils; -import com.alibaba.nacos.persistence.datasource.DataSourceService; -import com.alibaba.nacos.persistence.datasource.DynamicDataSource; -import com.alibaba.nacos.persistence.model.Page; -import com.alibaba.nacos.sys.env.EnvUtil; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.CannotGetJdbcConnectionException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.transaction.TransactionSystemException; -import org.springframework.transaction.support.TransactionTemplate; - -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_AGGR_ROW_MAPPER; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_CHANGED_ROW_MAPPER; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -@ExtendWith(SpringExtension.class) -class ExternalConfigInfoAggrPersistServiceImplTest { - - MockedStatic envUtilMockedStatic; - - MockedStatic externalStorageUtilsMockedStatic; - - MockedStatic dynamicDataSourceMockedStatic; - - @Mock - DynamicDataSource dynamicDataSource; - - private ExternalConfigInfoAggrPersistServiceImpl externalConfigInfoAggrPersistService; - - @Mock - private DataSourceService dataSourceService; - - @Mock - private JdbcTemplate jdbcTemplate; - - private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate(); - - @BeforeEach - void before() { - dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class); - envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); - externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class); - when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource); - when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService); - when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate); - when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate); - when(dataSourceService.getDataSourceType()).thenReturn("mysql"); - envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))).thenReturn(false); - externalConfigInfoAggrPersistService = new ExternalConfigInfoAggrPersistServiceImpl(); - - } - - @AfterEach - void after() { - dynamicDataSourceMockedStatic.close(); - envUtilMockedStatic.close(); - externalStorageUtilsMockedStatic.close(); - } - - @Test - void testAddAggrConfigInfoOfEqualContent() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId and equal with current content param. - String existContent = "content1234"; - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))).thenReturn( - existContent); - - boolean result = externalConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(result); - } - - @Test - void testAddAggrConfigInfoOfAddNewContent() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId and throw EmptyResultDataAccessException. - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))).thenThrow( - new EmptyResultDataAccessException(1)); - //mock insert success - when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(datumId), eq(appName), eq(content), - any(Timestamp.class))).thenReturn(1); - - //execute - boolean result = externalConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(result); - } - - @Test - void testAddAggrConfigInfoOfUpdateNotEqualContent() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId - String existContent = "existContent111"; - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))).thenReturn( - existContent); - //mock update success,return 1 - when(jdbcTemplate.update(anyString(), eq(content), any(Timestamp.class), eq(dataId), eq(group), eq(tenant), - eq(datumId))).thenReturn(1); - //mock update content - boolean result = externalConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(result); - - } - - @Test - void testAddAggrConfigInfoOfException() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - String datumId = "datumId"; - String appName = "appname1234"; - String content = "content1234"; - - //mock query datumId and throw EmptyResultDataAccessException. - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, datumId}), eq(String.class))).thenThrow( - new CannotGetJdbcConnectionException("mock exp")); - try { - externalConfigInfoAggrPersistService.addAggrConfigInfo(dataId, group, tenant, datumId, appName, content); - assertTrue(false); - } catch (Exception exp) { - assertEquals("mock exp", exp.getMessage()); - } - } - - @Test - void testBatchPublishAggrSuccess() { - - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - //mock query datumId and equal with current content param. - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, "d1"}), eq(String.class))).thenReturn("c1"); - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, "d2"}), eq(String.class))).thenReturn("c2"); - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, "d3"}), eq(String.class))).thenReturn("c3"); - Map datumMap = new HashMap<>(); - datumMap.put("d1", "c1"); - datumMap.put("d2", "c2"); - datumMap.put("d3", "c3"); - String appName = "appname1234"; - boolean result = externalConfigInfoAggrPersistService.batchPublishAggr(dataId, group, tenant, datumMap, appName); - assertTrue(result); - } - - @Test - void testBatchPublishAggrException() { - - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - //mock query datumId and equal with current content param. - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, "d1"}), eq(String.class))).thenThrow( - new TransactionSystemException("c1t fail")); - Map datumMap = new HashMap<>(); - datumMap.put("d1", "c1"); - datumMap.put("d2", "c2"); - datumMap.put("d3", "c3"); - String appName = "appname1234"; - boolean result = externalConfigInfoAggrPersistService.batchPublishAggr(dataId, group, tenant, datumMap, appName); - assertFalse(result); - } - - @Test - void testAggrConfigInfoCount() { - String dataId = "dataId11122"; - String group = "group"; - String tenant = "tenant"; - - //mock select count of aggr. - when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class), eq(dataId), eq(group), eq(tenant))).thenReturn(new Integer(101)); - int result = externalConfigInfoAggrPersistService.aggrConfigInfoCount(dataId, group, tenant); - assertEquals(101, result); - - } - - @Test - void testFindConfigInfoAggrByPage() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - - //mock query count. - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class))).thenReturn(101); - //mock query page list - List configInfoAggrs = new ArrayList<>(); - configInfoAggrs.add(new ConfigInfoAggr()); - configInfoAggrs.add(new ConfigInfoAggr()); - configInfoAggrs.add(new ConfigInfoAggr()); - - when(jdbcTemplate.query(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_AGGR_ROW_MAPPER))).thenReturn( - configInfoAggrs); - int pageNo = 1; - int pageSize = 120; - Page configInfoAggrByPage = externalConfigInfoAggrPersistService.findConfigInfoAggrByPage(dataId, group, tenant, - pageNo, pageSize); - assertEquals(101, configInfoAggrByPage.getTotalCount()); - assertEquals(configInfoAggrs, configInfoAggrByPage.getPageItems()); - - } - - @Test - void testFindConfigInfoAggrByPageOfException() { - String dataId = "dataId111"; - String group = "group"; - String tenant = "tenant"; - - //mock query count exception. - when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class))).thenThrow( - new CannotGetJdbcConnectionException("mock fail222")); - - try { - int pageNo = 1; - int pageSize = 120; - externalConfigInfoAggrPersistService.findConfigInfoAggrByPage(dataId, group, tenant, pageNo, pageSize); - assertTrue(false); - } catch (Throwable throwable) { - assertEquals("mock fail222", throwable.getMessage()); - } - } - - @Test - void testFindAllAggrGroup() { - List configList = new ArrayList<>(); - configList.add(create("dataId", 0)); - configList.add(create("dataId", 1)); - //mock return list - when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_CHANGED_ROW_MAPPER))).thenReturn(configList); - - List allAggrGroup = externalConfigInfoAggrPersistService.findAllAggrGroup(); - assertEquals(configList, allAggrGroup); - - } - - @Test - void testFindAllAggrGroupException() { - - //mock throw CannotGetJdbcConnectionException - when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_CHANGED_ROW_MAPPER))).thenThrow( - new CannotGetJdbcConnectionException("mock fail")); - try { - externalConfigInfoAggrPersistService.findAllAggrGroup(); - assertTrue(false); - } catch (Throwable throwable) { - assertEquals("mock fail", throwable.getMessage()); - } - - //mock throw EmptyResultDataAccessException - when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_CHANGED_ROW_MAPPER))).thenThrow( - new EmptyResultDataAccessException(1)); - List allAggrGroup = externalConfigInfoAggrPersistService.findAllAggrGroup(); - assertNull(allAggrGroup); - - //mock Exception - when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_CHANGED_ROW_MAPPER))).thenThrow( - new RuntimeException("789")); - try { - externalConfigInfoAggrPersistService.findAllAggrGroup(); - assertTrue(false); - } catch (Throwable throwable) { - assertEquals("789", throwable.getCause().getMessage()); - } - - } - - private ConfigInfoChanged create(String dataID, int i) { - ConfigInfoChanged hasDatum = new ConfigInfoChanged(); - hasDatum.setDataId(dataID + i); - hasDatum.setTenant("tenant1"); - hasDatum.setGroup("group1"); - return hasDatum; - } - -} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImplTest.java new file mode 100644 index 00000000000..7035ce4a77e --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImplTest.java @@ -0,0 +1,586 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.service.repository.extrnal; + +import com.alibaba.nacos.common.utils.MD5Utils; +import com.alibaba.nacos.config.server.model.ConfigInfo; +import com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper; +import com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper; +import com.alibaba.nacos.config.server.model.ConfigOperateResult; +import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; +import com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils; +import com.alibaba.nacos.config.server.utils.TestCaseUtils; +import com.alibaba.nacos.persistence.datasource.DataSourceService; +import com.alibaba.nacos.persistence.datasource.DynamicDataSource; +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.support.TransactionTemplate; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +import static com.alibaba.nacos.config.server.constant.Constants.ENCODE; +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER; +import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +@ExtendWith(SpringExtension.class) +public class ExternalConfigInfoGrayPersistServiceImplTest { + + private ExternalConfigInfoGrayPersistServiceImpl externalConfigInfoGrayPersistService; + + @Mock + private DataSourceService dataSourceService; + + @Mock + private JdbcTemplate jdbcTemplate; + + @Mock + private HistoryConfigInfoPersistService historyConfigInfoPersistService; + + @Mock + DatabaseOperate databaseOperate; + + private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate(); + + MockedStatic envUtilMockedStatic; + + MockedStatic externalStorageUtilsMockedStatic; + + MockedStatic dynamicDataSourceMockedStatic; + + @Mock + DynamicDataSource dynamicDataSource; + + /** + * before each tet case. + */ + @BeforeEach + public void before() { + dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class); + envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); + externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class); + when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource); + when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService); + when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate); + when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate); + when(dataSourceService.getDataSourceType()).thenReturn("mysql"); + envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))) + .thenReturn(false); + externalConfigInfoGrayPersistService = new ExternalConfigInfoGrayPersistServiceImpl(historyConfigInfoPersistService); + } + + /** + * after each test case. + */ + @AfterEach + public void after() { + dynamicDataSourceMockedStatic.close(); + envUtilMockedStatic.close(); + externalStorageUtilsMockedStatic.close(); + } + + @Test + public void testInsertOrUpdateGrayOfUpdate() { + String dataId = "grayDataId113"; + String group = "group"; + String tenant = "tenant"; + + //mock exist gray + ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + + //mock exist config info + ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper(); + configAllInfo4Gray.setDataId(dataId); + configAllInfo4Gray.setGroup(group); + configAllInfo4Gray.setTenant(tenant); + configAllInfo4Gray.setMd5("old_md5"); + String grayName = "grayName..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper); + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray); + + String srcIp = "srcUp..."; + String srcUser = "srcUser..."; + String appName = "appName"; + String content = "content111"; + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key34567"); + String grayRule = "grayRule..."; + ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, + grayName, grayRule, srcIp, srcUser); + //expect return obj + assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + //verify update to be invoked + Mockito.verify(jdbcTemplate, times(1)) + .update(anyString(), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()), + eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), + eq(dataId), eq(group), eq(tenant), eq(grayName)); + + } + + @Test + public void testInsertOrUpdateGrayOfAdd() { + String dataId = "betaDataId113"; + String group = "group113"; + String tenant = "tenant113"; + //mock exist beta + ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + String grayName = "grayName..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1)) + .thenReturn(mockedConfigInfoStateWrapper); + + String srcIp = "srcUp..."; + String srcUser = "srcUser..."; + String appName = "appname"; + String content = "content111"; + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key34567"); + String grayRule = "grayRule..."; + + //execute + ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, + grayName, grayRule, srcIp, srcUser); + //expect return obj + assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + //verify add to be invoked + Mockito.verify(jdbcTemplate, times(1)) + .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule), + eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()), + eq(configInfo.getMd5()), eq(srcIp), eq(srcUser)); + } + + @Test + public void testInsertOrUpdateGrayOfException() { + String dataId = "grapDataId113"; + String group = "group113"; + String tenant = "tenant113"; + + //mock exist gray + ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + String grayName = "grayName..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper); + + String srcIp = "srcUp..."; + String srcUser = "srcUser..."; + String appName = "appname"; + String content = "content111"; + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key34567"); + configInfo.setMd5("casMd5"); + String grayRule = "grayRule..."; + // mock update throw CannotGetJdbcConnectionException + when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()), + eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), + eq(dataId), eq(group), eq(tenant), eq(grayName))).thenThrow( + new CannotGetJdbcConnectionException("mock fail")); + //execute of update& expect. + try { + externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, grayName, grayRule, srcIp, srcUser); + assertTrue(false); + } catch (Exception exception) { + assertEquals("mock fail", exception.getMessage()); + } + + //mock query return null + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null); + //mock add throw CannotGetJdbcConnectionException + when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule), + eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()), + eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser))).thenThrow( + new CannotGetJdbcConnectionException("mock fail add")); + + //execute of add& expect. + try { + externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, grayName, grayRule, srcIp, srcUser); + assertTrue(false); + } catch (Exception exception) { + assertEquals("mock fail add", exception.getMessage()); + } + + //mock query throw CannotGetJdbcConnectionException + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow( + new CannotGetJdbcConnectionException("get c fail")); + //execute of add& expect. + try { + externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, grayName, grayRule, srcIp, srcUser); + assertTrue(false); + } catch (Exception exception) { + assertEquals("get c fail", exception.getMessage()); + } + + } + + @Test + public void testInsertOrUpdateGrayCasOfUpdate() { + String dataId = "grayDataId113"; + String group = "group"; + String tenant = "tenant"; + + //mock exist gray + ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + String grayName = "grayName..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper, + mockedConfigInfoStateWrapper); + + //execute + String srcIp = "srcUp..."; + String srcUser = "srcUser..."; + String appName = "appname"; + String content = "content111"; + + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key34567"); + configInfo.setMd5("casMd5"); + String grayRule = "grayRule..."; + //mock cas update + when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, ENCODE)), + eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), eq(dataId), eq(group), eq(tenant), + eq(grayName), eq(configInfo.getMd5()))).thenReturn(1); + + //mock exist config info + ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper(); + configAllInfo4Gray.setDataId(dataId); + configAllInfo4Gray.setGroup(group); + configAllInfo4Gray.setTenant(tenant); + configAllInfo4Gray.setMd5("old_md5"); + String grayName1 = "grayName1..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray); + + ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, + grayName, grayRule, srcIp, srcUser); + //expect return obj + assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + //verify cas update to be invoked + Mockito.verify(jdbcTemplate, times(1)) + .update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), + eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), eq(dataId), eq(group), eq(tenant), + eq(grayName), eq(configInfo.getMd5())); + + } + + @Test + public void testInsertOrUpdateGrayCasOfAdd() { + String dataId = "betaDataId113"; + String group = "group113"; + String tenant = "tenant113"; + + //mock exist beta + ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + String grayName = "grayName..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1)) + .thenReturn(mockedConfigInfoStateWrapper); + + String srcIp = "srcUp..."; + String srcUser = "srcUser..."; + String appName = "appname"; + String content = "content111"; + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key34567"); + configInfo.setMd5("csMd5"); + String grayRule = "grayRule..."; + //execute + ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, + grayName, grayRule, srcIp, srcUser); + //expect return obj + assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId()); + assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified()); + //verify add to be invoked + Mockito.verify(jdbcTemplate, times(1)) + .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule), + eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()), + eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser)); + + } + + @Test + public void testInsertOrUpdateGrayCasOfException() { + String dataId = "betaDataId113"; + String group = "group113"; + String tenant = "tenant113"; + + //mock exist beta + ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + String grayName = "grayName..."; + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper); + + String srcIp = "srcUp..."; + String srcUser = "srcUser..."; + String appName = "appname"; + String content = "content111"; + ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); + configInfo.setEncryptedDataKey("key34567"); + configInfo.setMd5("casMd5"); + String grayRule = "grayRule..."; + // mock update throw CannotGetJdbcConnectionException + when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, ENCODE)), + eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), eq(dataId), eq(group), eq(tenant), + eq(grayName), eq(configInfo.getMd5()))).thenThrow( + new CannotGetJdbcConnectionException("updat mock fail")); + + //execute of update& expect. + try { + externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, grayName, grayRule, srcIp, srcUser); + assertTrue(false); + } catch (Exception exception) { + assertEquals("updat mock fail", exception.getMessage()); + } + + //mock query return null + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null); + //mock add throw CannotGetJdbcConnectionException + when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule), + eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()), + eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser))).thenThrow( + new CannotGetJdbcConnectionException("mock fail add")); + + //execute of add& expect. + try { + externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, grayName, grayRule, srcIp, srcUser); + assertTrue(false); + } catch (Exception exception) { + assertEquals("mock fail add", exception.getMessage()); + } + + //mock query throw CannotGetJdbcConnectionException + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow( + new CannotGetJdbcConnectionException("get c fail")); + //execute of add& expect. + try { + externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, grayName, grayRule, srcIp, srcUser); + assertTrue(false); + } catch (Exception exception) { + assertEquals("get c fail", exception.getMessage()); + } + + } + + @Test + void testRemoveConfigInfo() { + String dataId = "dataId4567"; + String group = "group3456789"; + String tenant = "tenant4567890"; + final String grayName = "grayName1"; + + //mock exist config info + ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper(); + configAllInfo4Gray.setDataId(dataId); + configAllInfo4Gray.setGroup(group); + configAllInfo4Gray.setTenant(tenant); + configAllInfo4Gray.setMd5("old_md5"); + + Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))) + .thenReturn(configAllInfo4Gray); + Mockito.when(databaseOperate.update(any())).thenReturn(true); + + String srcIp = "srcIp1234"; + String srcUser = "srcUser"; + externalConfigInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, grayName, srcIp, srcUser); + + Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName)); + Mockito.verify(historyConfigInfoPersistService, times(1)).insertConfigHistoryAtomic( + eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("D"), + eq("gray"), anyString()); + + // Test the exception handling for CannotGetJdbcConnectionException + when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName))) + .thenThrow(new CannotGetJdbcConnectionException("mock fail11111")); + + } + + @Test + public void testFindChangeConfigInfo4Gray() { + List mockList = new ArrayList<>(); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.get(0).setLastModified(System.currentTimeMillis()); + mockList.get(1).setLastModified(System.currentTimeMillis()); + mockList.get(2).setLastModified(System.currentTimeMillis()); + + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + + long lastMaxId = 123; + when(jdbcTemplate.query(anyString(), eq(new Object[] {timestamp, lastMaxId, 100}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockList) + .thenThrow(new CannotGetJdbcConnectionException("mock exception22")); + + List changeConfig = externalConfigInfoGrayPersistService.findChangeConfig(timestamp, + lastMaxId, 100); + assertTrue(changeConfig.get(0).getLastModified() == mockList.get(0).getLastModified()); + assertTrue(changeConfig.get(1).getLastModified() == mockList.get(1).getLastModified()); + assertTrue(changeConfig.get(2).getLastModified() == mockList.get(2).getLastModified()); + try { + externalConfigInfoGrayPersistService.findChangeConfig(timestamp, lastMaxId, 100); + assertTrue(false); + } catch (CannotGetJdbcConnectionException exception) { + assertEquals("mock exception22", exception.getMessage()); + } + + } + + @Test + public void testFindConfigInfo4Gray() { + String dataId = "dataId456789"; + String group = "group4567"; + String tenant = "tenant56789o0"; + String grayName = "gray12"; + //mock exist gray + ConfigInfoGrayWrapper mockedConfigInfoStateWrapper = new ConfigInfoGrayWrapper(); + mockedConfigInfoStateWrapper.setDataId(dataId); + mockedConfigInfoStateWrapper.setGroup(group); + mockedConfigInfoStateWrapper.setGrayName(grayName); + mockedConfigInfoStateWrapper.setTenant(tenant); + mockedConfigInfoStateWrapper.setId(123456L); + mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis()); + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper); + ConfigInfoGrayWrapper configInfo4GrayReturn = externalConfigInfoGrayPersistService.findConfigInfo4Gray(dataId, + group, tenant, grayName); + assertEquals(mockedConfigInfoStateWrapper, configInfo4GrayReturn); + + //mock query throw CannotGetJdbcConnectionException + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenThrow( + new CannotGetJdbcConnectionException("mock fail11111")); + try { + externalConfigInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant, grayName); + assertTrue(false); + } catch (Exception exception) { + assertEquals("mock fail11111", exception.getMessage()); + } + + //mock query throw EmptyResultDataAccessException + when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}), + eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1)); + ConfigInfoGrayWrapper configInfo4GrayNull = externalConfigInfoGrayPersistService.findConfigInfo4Gray(dataId, + group, tenant, grayName); + assertNull(configInfo4GrayNull); + } + + @Test + public void testConfigInfoGrayCount() { + when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(101); + int returnCount = externalConfigInfoGrayPersistService.configInfoGrayCount(); + assertEquals(101, returnCount); + } + + @Test + public void testFindAllConfigInfoGrayForDumpAll() { + //mock count + when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(12345); + + //mock page list + List mockList = new ArrayList<>(); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.add(new ConfigInfoGrayWrapper()); + mockList.get(0).setLastModified(System.currentTimeMillis()); + mockList.get(1).setLastModified(System.currentTimeMillis()); + mockList.get(2).setLastModified(System.currentTimeMillis()); + + when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn( + mockList); + + int pageNo = 1; + int pageSize = 101; + when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(101); + //execute & expect + Page pageReturn = externalConfigInfoGrayPersistService.findAllConfigInfoGrayForDumpAll( + pageNo, pageSize); + assertEquals(mockList, pageReturn.getPageItems()); + assertEquals(101, pageReturn.getTotalCount()); + + //mock count throw CannotGetJdbcConnectionException + when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenThrow( + new CannotGetJdbcConnectionException("345678909fail")); + //execute &expect + try { + externalConfigInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(pageNo, pageSize); + assertTrue(false); + } catch (Exception exception) { + assertEquals("345678909fail", exception.getMessage()); + } + } + +} + diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImplTest.java index bab2bc8cf48..37d7614afe0 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImplTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImplTest.java @@ -29,6 +29,7 @@ import com.alibaba.nacos.config.server.model.SameConfigPolicy; import com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService; import com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils; +import com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil; import com.alibaba.nacos.config.server.utils.TestCaseUtils; import com.alibaba.nacos.persistence.datasource.DataSourceService; import com.alibaba.nacos.persistence.datasource.DynamicDataSource; @@ -161,7 +162,8 @@ void testInsertOrUpdateOfInsertConfigSuccess() { String srcUser = "srcUser"; //mock insert config info Mockito.doNothing().when(historyConfigInfoPersistService) - .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), + eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); externalConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo); //expect insert config info @@ -180,7 +182,8 @@ void testInsertOrUpdateOfInsertConfigSuccess() { //expect insert history info Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), + eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); } @@ -215,7 +218,8 @@ void testInsertOrUpdateCasOfInsertConfigSuccess() { String srcUser = "srcUser"; //mock insert config info Mockito.doNothing().when(historyConfigInfoPersistService) - .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), + eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); externalConfigInfoPersistService.insertOrUpdateCas(srcIp, srcUser, configInfo, configAdvanceInfo); //expect insert config info @@ -234,7 +238,8 @@ void testInsertOrUpdateCasOfInsertConfigSuccess() { //expect insert history info Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq("I")); + .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), + eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser))); } @@ -286,17 +291,18 @@ void testInsertOrUpdateOfUpdateConfigSuccess() { //mock get config state,first and second is not null Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper()); + + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + //mock get all config info + Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), + eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo); - //mock select config info before update - ConfigInfoWrapper configInfoWrapperOld = new ConfigInfoWrapper(); - configInfoWrapperOld.setDataId(dataId); - configInfoWrapperOld.setGroup(group); - configInfoWrapperOld.setTenant(tenant); - configInfoWrapperOld.setAppName("old_app"); - configInfoWrapperOld.setMd5("old_md5"); - configInfoWrapperOld.setId(12345678765L); - Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))) - .thenReturn(configInfoWrapperOld); String srcIp = "srcIp"; String srcUser = "srcUser"; //mock update config info @@ -304,7 +310,7 @@ void testInsertOrUpdateOfUpdateConfigSuccess() { TableConstant.CONFIG_INFO) .update(Arrays.asList("content", "md5", "src_ip", "src_user", "gmt_modified@NOW()", "app_name", "c_desc", "c_use", "effect", "type", "c_schema", "encrypted_data_key"), Arrays.asList("data_id", "group_id", "tenant_id"))), - eq(configInfo.getContent()), eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(configInfoWrapperOld.getAppName()), + eq(configInfo.getContent()), eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(configAllInfo.getAppName()), eq(configAdvanceInfo.get("desc")), eq(configAdvanceInfo.get("use")), eq(configAdvanceInfo.get("effect")), eq(configAdvanceInfo.get("type")), eq(configAdvanceInfo.get("schema")), eq(encryptedDataKey), eq(configInfo.getDataId()), eq(configInfo.getGroup()), eq(tenant))).thenReturn(1); @@ -317,8 +323,8 @@ void testInsertOrUpdateOfUpdateConfigSuccess() { //mock insert his config info Mockito.doNothing().when(historyConfigInfoPersistService) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), - eq("I")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser), + any(Timestamp.class), eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); externalConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo); @@ -327,17 +333,17 @@ void testInsertOrUpdateOfUpdateConfigSuccess() { externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION) .insert(Arrays.asList("id", "tag_name", "tag_type", "data_id", "group_id", "tenant_id"))), - eq(configInfoWrapperOld.getId()), eq("tag1"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); + eq(configAllInfo.getId()), eq("tag1"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); Mockito.verify(jdbcTemplate, times(1)).update(eq( externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION) .insert(Arrays.asList("id", "tag_name", "tag_type", "data_id", "group_id", "tenant_id"))), - eq(configInfoWrapperOld.getId()), eq("tag2"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); + eq(configAllInfo.getId()), eq("tag2"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); //expect insert history info Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), - any(Timestamp.class), eq("U")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), + eq(srcUser), any(Timestamp.class), eq("U"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); } @@ -364,40 +370,42 @@ void testInsertOrUpdateCasOfUpdateConfigSuccess() { Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper()); - //mock select config info before update - ConfigInfoWrapper configInfoWrapperOld = new ConfigInfoWrapper(); - configInfoWrapperOld.setDataId(dataId); - configInfoWrapperOld.setGroup(group); - configInfoWrapperOld.setTenant(tenant); - configInfoWrapperOld.setAppName("old_app11"); - configInfoWrapperOld.setMd5("old_md5"); - configInfoWrapperOld.setId(123456799L); - Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[]{dataId, group, tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))) - .thenReturn(configInfoWrapperOld); + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + //mock get all config info + Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), + eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo); + String srcIp = "srcIp"; String srcUser = "srcUser"; //mock update config info cas Mockito.when(jdbcTemplate.update(anyString(), eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), - eq(srcIp), eq(srcUser), eq(configInfoWrapperOld.getAppName()), eq(configAdvanceInfo.get("desc")), + eq(srcIp), eq(srcUser), eq(configAllInfo.getAppName()), eq(configAdvanceInfo.get("desc")), eq(configAdvanceInfo.get("use")), eq(configAdvanceInfo.get("effect")), eq(configAdvanceInfo.get("type")), eq(configAdvanceInfo.get("schema")), eq(encryptedDataKey), eq(dataId), eq(group), eq(tenant), eq(casMd5))).thenReturn(1); //mock insert config tags. Mockito.when(jdbcTemplate.update(eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION) - .insert(Arrays.asList("id", "tag_name", "tag_type", "data_id", "group_id", "tenant_id"))), eq(configInfoWrapperOld.getId()), - anyString(), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant))).thenReturn(1); - + .insert(Arrays.asList("id", "tag_name", "tag_type", "data_id", "group_id", "tenant_id"))), + eq(configAllInfo.getId()), anyString(), eq(StringUtils.EMPTY), eq(dataId), eq(group), + eq(tenant))).thenReturn(1); + //mock insert his config info Mockito.doNothing().when(historyConfigInfoPersistService) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), - eq("I")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser), + any(Timestamp.class), eq("I"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); externalConfigInfoPersistService.insertOrUpdateCas(srcIp, srcUser, configInfo, configAdvanceInfo); //expect update config cas Mockito.verify(jdbcTemplate, times(1)) .update(anyString(), eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), - eq(srcUser), eq(configInfoWrapperOld.getAppName()), eq(configAdvanceInfo.get("desc")), + eq(srcUser), eq(configAllInfo.getAppName()), eq(configAdvanceInfo.get("desc")), eq(configAdvanceInfo.get("use")), eq(configAdvanceInfo.get("effect")), eq(configAdvanceInfo.get("type")), eq(configAdvanceInfo.get("schema")), eq(encryptedDataKey), eq(dataId), eq(group), eq(tenant), eq(casMd5)); @@ -406,17 +414,17 @@ void testInsertOrUpdateCasOfUpdateConfigSuccess() { externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION) .insert(Arrays.asList("id", "tag_name", "tag_type", "data_id", "group_id", "tenant_id"))), - eq(configInfoWrapperOld.getId()), eq("tag1"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); + eq(configAllInfo.getId()), eq("tag1"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); Mockito.verify(jdbcTemplate, times(1)).update(eq( externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION) .insert(Arrays.asList("id", "tag_name", "tag_type", "data_id", "group_id", "tenant_id"))), - eq(configInfoWrapperOld.getId()), eq("tag2"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); + eq(configAllInfo.getId()), eq("tag2"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)); //expect insert history info Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), - any(Timestamp.class), eq("U")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser), + any(Timestamp.class), eq("U"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); } @@ -455,18 +463,18 @@ void testRemoveConfigInfo() { String group = "group3456789"; String tenant = "tenant4567890"; - //mock exist config info - ConfigInfoWrapper configInfoWrapperOld = new ConfigInfoWrapper(); - configInfoWrapperOld.setDataId(dataId); - configInfoWrapperOld.setGroup(group); - configInfoWrapperOld.setTenant(tenant); - configInfoWrapperOld.setAppName("old_app"); - configInfoWrapperOld.setContent("old content"); - configInfoWrapperOld.setMd5("old_md5"); - configInfoWrapperOld.setId(12345678765L); - configInfoWrapperOld.setEncryptedDataKey("key3456"); - Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))) - .thenReturn(configInfoWrapperOld); + //mock exist all config info + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + + Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), + eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo); + String srcIp = "srcIp1234"; String srcUser = "srcUser"; externalConfigInfoPersistService.removeConfigInfo(dataId, group, tenant, srcIp, srcUser); @@ -474,11 +482,11 @@ void testRemoveConfigInfo() { //expect delete to be invoked Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(dataId), eq(group), eq(tenant)); //expect delete tags to be invoked - Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(configInfoWrapperOld.getId())); + Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(configAllInfo.getId())); //expect insert delete history Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfoWrapperOld.getId()), eq(configInfoWrapperOld), eq(srcIp), eq(srcUser), any(), - eq("D")); + .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configAllInfo), eq(srcIp), + eq(srcUser), any(), eq("D"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo))); } @@ -486,13 +494,24 @@ void testRemoveConfigInfo() { void testRemoveConfigInfoByIds() { //mock exist config info - List configInfos = new ArrayList<>(); - configInfos.add(new ConfigInfo("data1", "group", "tenant", "app", "content")); - configInfos.add(new ConfigInfo("data2", "grou2", "tenan2", "app2", "content2")); + final List configAllInfos = new ArrayList<>(); + final ConfigAllInfo configAllInfo1 = new ConfigAllInfo(); + final ConfigAllInfo configAllInfo2 = new ConfigAllInfo(); + configAllInfo1.setDataId("dataId1"); + configAllInfo1.setGroup("group1"); + configAllInfo1.setTenant("tenant1"); + configAllInfo1.setAppName("app1"); + configAllInfo2.setDataId("dataId2"); + configAllInfo2.setGroup("group2"); + configAllInfo2.setTenant("tenant2"); + configAllInfo2.setAppName("app2"); + configAllInfos.add(configAllInfo1); + configAllInfos.add(configAllInfo2); List deleteIds = Arrays.asList(12344L, 3456789L); - configInfos.get(0).setId(12344L); - configInfos.get(1).setId(3456789L); - Mockito.when(jdbcTemplate.query(anyString(), eq(deleteIds.toArray()), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(configInfos); + configAllInfos.get(0).setId(12344L); + configAllInfos.get(1).setId(3456789L); + Mockito.when(jdbcTemplate.query(anyString(), eq(deleteIds.toArray()), eq(CONFIG_ALL_INFO_ROW_MAPPER))) + .thenReturn(configAllInfos); String srcIp = "srcIp1234"; String srcUser = "srcUser"; externalConfigInfoPersistService.removeConfigInfoByIds(deleteIds, srcIp, srcUser); @@ -504,9 +523,11 @@ void testRemoveConfigInfoByIds() { Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(1))); //expect insert delete history Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfos.get(0).getId()), eq(configInfos.get(0)), eq(srcIp), eq(srcUser), any(), eq("D")); + .insertConfigHistoryAtomic(eq(configAllInfos.get(0).getId()), eq(configAllInfos.get(0)), eq(srcIp), eq(srcUser), + any(), eq("D"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(0)))); Mockito.verify(historyConfigInfoPersistService, times(1)) - .insertConfigHistoryAtomic(eq(configInfos.get(1).getId()), eq(configInfos.get(1)), eq(srcIp), eq(srcUser), any(), eq("D")); + .insertConfigHistoryAtomic(eq(configAllInfos.get(1).getId()), eq(configAllInfos.get(1)), + eq(srcIp), eq(srcUser), any(), eq("D"), eq("formal"), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(0)))); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImplTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImplTest.java index e7509fd31ba..85bdaee3a22 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImplTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImplTest.java @@ -42,7 +42,6 @@ import java.util.ArrayList; import java.util.List; -import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER; import static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -107,20 +106,21 @@ void testInsertConfigHistoryAtomic() { String srcUser = "user12345"; String srcIp = "ip1234"; String ops = "D"; + String extraInfo = "type\":\"properties"; Timestamp timestamp = new Timestamp(System.currentTimeMillis()); ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content); configInfo.setEncryptedDataKey("key23456"); //expect insert success,verify insert invoked - externalHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp, ops); + externalHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp, ops, "formal", extraInfo); Mockito.verify(jdbcTemplate, times(1)) .update(anyString(), eq(id), eq(dataId), eq(group), eq(tenant), eq(appName), eq(content), eq(configInfo.getMd5()), - eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq(configInfo.getEncryptedDataKey())); + eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq("formal"), eq(extraInfo), eq(configInfo.getEncryptedDataKey())); - Mockito.when(jdbcTemplate.update(anyString(), eq(id), eq(dataId), eq(group), eq(tenant), eq(appName), eq(content), - eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq(configInfo.getEncryptedDataKey()))) + Mockito.when(jdbcTemplate.update(anyString(), eq(id), eq(dataId), eq(group), eq(tenant), eq(appName), eq(content), eq(configInfo.getMd5()), + eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq("formal"), eq(extraInfo), eq(configInfo.getEncryptedDataKey()))) .thenThrow(new CannotGetJdbcConnectionException("mock ex...")); try { - externalHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp, ops); + externalHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp, ops, "formal", extraInfo); assertTrue(false); } catch (Exception e) { assertEquals("mock ex...", e.getMessage()); @@ -140,47 +140,49 @@ void testRemoveConfigHistory() { void testFindDeletedConfig() { //mock query list return - ConfigInfoStateWrapper mockObj1 = new ConfigInfoStateWrapper(); + ConfigHistoryInfo mockObj1 = new ConfigHistoryInfo(); mockObj1.setDataId("data_id1"); mockObj1.setGroup("group_id1"); mockObj1.setTenant("tenant_id1"); mockObj1.setMd5("md51"); - mockObj1.setLastModified(System.currentTimeMillis()); + mockObj1.setLastModifiedTime(new Timestamp(System.currentTimeMillis())); - List list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(mockObj1); - ConfigInfoStateWrapper mockObj2 = new ConfigInfoStateWrapper(); + ConfigHistoryInfo mockObj2 = new ConfigHistoryInfo(); mockObj2.setDataId("data_id2"); mockObj2.setGroup("group_id2"); mockObj2.setTenant("tenant_id2"); mockObj2.setMd5("md52"); + mockObj2.setLastModifiedTime(new Timestamp(System.currentTimeMillis())); list.add(mockObj2); int pageSize = 1233; long startId = 23456; Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + String publishType = "formal"; Mockito.when( - jdbcTemplate.query(anyString(), eq(new Object[] {timestamp, startId, pageSize}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))) + jdbcTemplate.query(anyString(), eq(new Object[] {publishType, timestamp, startId, pageSize}), eq(HISTORY_DETAIL_ROW_MAPPER))) .thenReturn(list); //execute List deletedConfig = externalHistoryConfigInfoPersistService.findDeletedConfig(timestamp, startId, - pageSize); + pageSize, "formal"); //expect verify assertEquals("data_id1", deletedConfig.get(0).getDataId()); assertEquals("group_id1", deletedConfig.get(0).getGroup()); assertEquals("tenant_id1", deletedConfig.get(0).getTenant()); - assertEquals(mockObj1.getLastModified(), deletedConfig.get(0).getLastModified()); + assertEquals(mockObj1.getLastModifiedTime(), new Timestamp(deletedConfig.get(0).getLastModified())); assertEquals("data_id2", deletedConfig.get(1).getDataId()); assertEquals("group_id2", deletedConfig.get(1).getGroup()); assertEquals("tenant_id2", deletedConfig.get(1).getTenant()); - assertEquals(mockObj2.getLastModified(), deletedConfig.get(1).getLastModified()); + assertEquals(mockObj2.getLastModifiedTime(), new Timestamp(deletedConfig.get(1).getLastModified())); //mock exception Mockito.when( - jdbcTemplate.query(anyString(), eq(new Object[] {timestamp, startId, pageSize}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))) - .thenThrow(new CannotGetJdbcConnectionException("conn error")); + jdbcTemplate.query(anyString(), eq(new Object[] {publishType, timestamp, startId, pageSize}), + eq(HISTORY_DETAIL_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException("conn error")); try { - externalHistoryConfigInfoPersistService.findDeletedConfig(timestamp, startId, pageSize); + externalHistoryConfigInfoPersistService.findDeletedConfig(timestamp, startId, pageSize, "formal"); assertTrue(false); } catch (Exception e) { assertEquals("conn error", e.getMessage()); diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtilTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtilTest.java new file mode 100644 index 00000000000..d9d6ff0c1f8 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtilTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.config.server.utils; + +import com.alibaba.nacos.api.config.ConfigType; +import com.alibaba.nacos.config.server.model.ConfigAllInfo; +import com.alibaba.nacos.config.server.model.gray.BetaGrayRule; +import com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo; +import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; +import org.junit.jupiter.api.Test; + +import static com.alibaba.nacos.config.server.model.gray.BetaGrayRule.PRIORITY; + +public class ConfigExtInfoUtilTest { + + @Test + void testExt4Formal() { + + String dataId = "dataId4567"; + String group = "group3456789"; + String tenant = "tenant4567890"; + + //mock exist config info + ConfigAllInfo configAllInfo = new ConfigAllInfo(); + configAllInfo.setDataId(dataId); + configAllInfo.setGroup(group); + configAllInfo.setTenant(tenant); + configAllInfo.setAppName("old_app"); + configAllInfo.setMd5("old_md5"); + configAllInfo.setId(12345678765L); + configAllInfo.setType(ConfigType.JSON.getType()); + configAllInfo.setSchema("testschema"); + configAllInfo.setCreateUser("testuser"); + configAllInfo.setEffect("online"); + configAllInfo.setDesc("desc"); + configAllInfo.setUse("use124"); + configAllInfo.setConfigTags("ctag1,ctag2"); + String extraInfoFromAllInfo = ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo); + System.out.println(extraInfoFromAllInfo); + + } + + @Test + void testExt4Gray() { + String grayName = "gray124"; + ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA, + BetaGrayRule.VERSION, "127.0.0.1,127.0.0.2", PRIORITY); + + String grayRule = GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo); + String oldSrcUser = "user132"; + String extraInfoFromAllInfo = ConfigExtInfoUtil.getExtInfoFromGrayInfo(grayName, grayRule, oldSrcUser); + System.out.println(extraInfoFromAllInfo); + + } +} + diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/PropertyUtilTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/PropertyUtilTest.java index 5224b7c62ea..49df4cf84e5 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/utils/PropertyUtilTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/PropertyUtilTest.java @@ -43,8 +43,8 @@ class PropertyUtilTest { @BeforeEach void setUp() { envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); - envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq("memory_limit_file_path"), eq("/sys/fs/cgroup/memory/memory.limit_in_bytes"))) - .thenReturn(mockMem); + envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq("memory_limit_file_path"), + eq("/sys/fs/cgroup/memory/memory.limit_in_bytes"))).thenReturn(mockMem); } @@ -76,6 +76,10 @@ private void clearAllDumpFiled() throws Exception { Field allDumpPageSizeFiled = FieldUtils.getField(PropertyUtil.class, "allDumpPageSize"); allDumpPageSizeFiled.setAccessible(true); allDumpPageSizeFiled.set(null, null); + + Field limitMemoryFileFiled = FieldUtils.getField(PropertyUtil.class, "limitMemoryFile"); + limitMemoryFileFiled.setAccessible(true); + limitMemoryFileFiled.set(null, null); } @Test diff --git a/console-ui/src/locales/en-US.js b/console-ui/src/locales/en-US.js index 6a3e4b597cf..f1886e81d60 100644 --- a/console-ui/src/locales/en-US.js +++ b/console-ui/src/locales/en-US.js @@ -254,6 +254,9 @@ const I18N_CONF = { lastUpdateTime: 'Last Modified At', operator: 'Operator', operation: 'Operation', + publishType: 'Publish Type', + formal: 'Formal Version', + gray: 'Gray Version', compare: 'Compare', historyCompareTitle: 'History Compare', historyCompareLastVersion: 'Lasted Release Version', @@ -273,6 +276,11 @@ const I18N_CONF = { configureContent: 'Configuration Content', back: 'Back', namespace: 'Namespace', + publishType: 'Publish Type', + formal: 'Formal Version', + gray: 'Gray Version', + grayVersion: 'Gray Version', + grayRule: 'Gray Rule', }, DashboardCard: { importantReminder0: 'Important reminder', diff --git a/console-ui/src/locales/zh-CN.js b/console-ui/src/locales/zh-CN.js index 5ecb1fc254f..aa8222ce8a1 100644 --- a/console-ui/src/locales/zh-CN.js +++ b/console-ui/src/locales/zh-CN.js @@ -251,6 +251,9 @@ const I18N_CONF = { articleMeetRequirements: '条满足要求的配置。', lastUpdateTime: '最后更新时间', operator: '操作人', + publishType: '发布类型', + formal: '正式版本', + gray: '灰度版本', operation: '操作', compare: '比较', historyCompareTitle: '历史版本比较', @@ -271,6 +274,11 @@ const I18N_CONF = { sourceIp: '来源 IP', back: '返回', namespace: '命名空间', + publishType: '发布类型', + formal: '正式版本', + gray: '灰度版本', + grayVersion: '灰度版本', + grayRule: '灰度规则', }, DashboardCard: { importantReminder0: '重要提醒', diff --git a/console-ui/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js b/console-ui/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js index 25dd6399ded..69b153943cb 100644 --- a/console-ui/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js +++ b/console-ui/src/pages/ConfigurationManagement/ConfigEditor/NewConfigEditor.js @@ -104,7 +104,7 @@ class ConfigEditor extends React.Component { }, () => { this.getConfig(true).then(res => { - if (res.code !== 200 || !res.data) { + if (res.code !== 0 || !res.data) { this.getConfig(); return; } diff --git a/console-ui/src/pages/ConfigurationManagement/ConfigRollback/ConfigRollback.js b/console-ui/src/pages/ConfigurationManagement/ConfigRollback/ConfigRollback.js index 4cf03764a7a..51802abd430 100644 --- a/console-ui/src/pages/ConfigurationManagement/ConfigRollback/ConfigRollback.js +++ b/console-ui/src/pages/ConfigurationManagement/ConfigRollback/ConfigRollback.js @@ -39,6 +39,7 @@ class ConfigRollback extends React.Component { envName: '', visible: false, showmore: false, + extraInfo: {}, }; // this.params = window.location.hash.split('?')[1]||''; } @@ -68,6 +69,7 @@ class ConfigRollback extends React.Component { toggleMore() { this.setState({ showmore: !this.state.showmore, + extraInfo: data.extraInfo ? JSON.parse(data.extraInfo) : {}, }); } @@ -93,6 +95,7 @@ class ConfigRollback extends React.Component { self.field.setValue('envName', envName); self.setState({ envName, + extraInfo: data.extraInfo ? JSON.parse(data.extraInfo) : {}, }); } }, @@ -138,12 +141,19 @@ class ConfigRollback extends React.Component { self.serverId = getParams('serverId') || 'center'; self.dataId = self.field.getValue('dataId'); self.group = self.field.getValue('group'); + const { extraInfo } = self.state; let postData = { appName: self.field.getValue('appName'), dataId: self.dataId, groupName: self.group, content: self.field.getValue('content'), namespaceId: self.tenant, + ...(extraInfo.type ? { type: extraInfo.type } : {}), + ...(extraInfo.config_tags ? { config_tags: extraInfo.config_tags } : {}), + ...(extraInfo.effect ? { effect: extraInfo.effect } : {}), + ...(extraInfo.c_desc ? { desc: extraInfo.c_desc } : {}), + ...(extraInfo.c_use ? { use: extraInfo.c_use } : {}), + ...(extraInfo.c_schema ? { schema: extraInfo.c_schema } : {}), }; let url = 'v3/console/cs/config'; diff --git a/console-ui/src/pages/ConfigurationManagement/HistoryDetail/HistoryDetail.js b/console-ui/src/pages/ConfigurationManagement/HistoryDetail/HistoryDetail.js index 2b7d79bf366..1f72123f078 100644 --- a/console-ui/src/pages/ConfigurationManagement/HistoryDetail/HistoryDetail.js +++ b/console-ui/src/pages/ConfigurationManagement/HistoryDetail/HistoryDetail.js @@ -34,6 +34,9 @@ class HistoryDetail extends React.Component { super(props); this.state = { showmore: false, + currentPublishType: '', + grayVersion: '', + grayRule: '', }; this.edasAppName = getParams('edasAppName'); this.edasAppId = getParams('edasAppId'); @@ -65,6 +68,8 @@ class HistoryDetail extends React.Component { success(result) { if (result != null) { const data = result.data; + const extInfo = data.extInfo ? JSON.parse(data.extInfo) : {}; + const grayRule = extInfo.gray_rule ? JSON.parse(extInfo.gray_rule) : {}; self.field.setValue('dataId', data.dataId); self.field.setValue('content', data.content); self.field.setValue('appName', self.inApp ? self.edasAppName : data.appName); @@ -74,6 +79,13 @@ class HistoryDetail extends React.Component { self.field.setValue('opType', data.opType.trim()); self.field.setValue('group', data.group); self.field.setValue('md5', data.md5); + self.setState({ + currentPublishType: data.publishType, + ...(data.publishType === 'gray' && { + grayVersion: grayRule.version || '', + grayRule: grayRule.expr || '', + }), + }); } }, }); @@ -100,6 +112,7 @@ class HistoryDetail extends React.Component { render() { const { locale = {} } = this.props; const { init } = this.field; + const { currentPublishType, grayVersion, grayRule } = this.state; const formItemLayout = { labelCol: { fixedSpan: 6, @@ -132,6 +145,23 @@ class HistoryDetail extends React.Component { + + + + {currentPublishType === 'gray' && ( + <> + + + + + + + + )} diff --git a/console-ui/src/pages/ConfigurationManagement/HistoryRollback/HistoryRollback.js b/console-ui/src/pages/ConfigurationManagement/HistoryRollback/HistoryRollback.js index b004c46b081..682aea3cd03 100644 --- a/console-ui/src/pages/ConfigurationManagement/HistoryRollback/HistoryRollback.js +++ b/console-ui/src/pages/ConfigurationManagement/HistoryRollback/HistoryRollback.js @@ -139,13 +139,21 @@ class HistoryRollback extends React.Component { renderCol(value, index, record) { const { locale = {} } = this.props; + const isBeta = record.publishType === 'gray'; return (

{locale.details} | - + {locale.rollback} | @@ -438,6 +446,23 @@ class HistoryRollback extends React.Component { + { + if (value === 'formal') { + return locale.formal; + } else if (value === 'gray') { + const extraInfo = record.extraInfo ? JSON.parse(record.extraInfo) : {}; + if (extraInfo.gray_name) { + return `${locale.gray}(${extraInfo.gray_name})`; + } else { + return locale.gray; + } + } + return value; + }} + /> ids, String clientIp, String srcUser) { final Timestamp time = TimeUtils.getCurrentTime(); - List configInfoList = configInfoPersistService.removeConfigInfoByIds(ids, clientIp, srcUser); + List configInfoList = configInfoPersistService.removeConfigInfoByIds(ids, clientIp, srcUser); if (CollectionUtils.isEmpty(configInfoList)) { return true; } for (ConfigInfo configInfo : configInfoList) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configInfo.getDataId(), configInfo.getGroup(), - configInfo.getTenant(), time.getTime())); + new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), + time.getTime())); ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), null, time.getTime(), clientIp, ConfigTraceService.PERSISTENCE_EVENT, @@ -203,7 +203,8 @@ public GroupkeyListenserStatus getListeners(String dataId, String group, String } @Override - public GroupkeyListenserStatus getAllSubClientConfigByIp(String ip, boolean all, String namespaceId, int sampleTime) { + public GroupkeyListenserStatus getAllSubClientConfigByIp(String ip, boolean all, String namespaceId, + int sampleTime) { SampleResult collectSampleResult = configSubService.getCollectSampleResultByIp(ip, sampleTime); GroupkeyListenserStatus gls = new GroupkeyListenserStatus(); gls.setCollectStatus(200); @@ -346,8 +347,8 @@ public Result> importAndPublishConfig(String srcUser, String null, policy); for (ConfigInfo configInfo : configInfoList) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configInfo.getDataId(), configInfo.getGroup(), - configInfo.getTenant(), time.getTime())); + new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), + time.getTime())); ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB, @@ -578,7 +579,7 @@ public Result> cloneConfig(String srcUser, String namespaceI srcIp, null, policy); for (ConfigInfo configInfo : configInfoList4Clone) { ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(false, configInfo.getDataId(), configInfo.getGroup(), + new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), time.getTime())); ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(), @@ -600,7 +601,7 @@ public boolean removeBetaConfig(String dataId, String group, String namespaceId, ConfigTraceService.logPersistenceEvent(dataId, group, namespaceId, requestIpApp, System.currentTimeMillis(), remoteIp, ConfigTraceService.PERSISTENCE_EVENT_BETA, ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null); ConfigChangePublisher.notifyConfigChange( - new ConfigDataChangeEvent(true, dataId, group, namespaceId, System.currentTimeMillis())); + new ConfigDataChangeEvent(dataId, group, namespaceId, BetaGrayRule.TYPE_BETA, System.currentTimeMillis())); return true; } @@ -609,7 +610,7 @@ public boolean removeBetaConfig(String dataId, String group, String namespaceId, public Result queryBetaConfig(String dataId, String group, String namespaceId) { try { ConfigInfo4Beta ci = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, namespaceId); - + if (Objects.nonNull(ci)) { String encryptedDataKey = ci.getEncryptedDataKey(); Pair pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, ci.getContent()); diff --git a/console/src/main/resources/META-INF/derby-schema.sql b/console/src/main/resources/META-INF/derby-schema.sql index be595491b89..fee73d47975 100644 --- a/console/src/main/resources/META-INF/derby-schema.sql +++ b/console/src/main/resources/META-INF/derby-schema.sql @@ -54,6 +54,8 @@ CREATE TABLE his_config_info ( gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', src_user varchar(128), src_ip varchar(50) DEFAULT NULL, + publish_type varchar(50) DEFAULT 'formal', + ext_info CLOB, op_type char(10) DEFAULT NULL, encrypted_data_key LONG VARCHAR DEFAULT NULL, constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); @@ -96,17 +98,25 @@ CREATE TABLE config_info_tag ( constraint configinfotag_id_key PRIMARY KEY (id), constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); -CREATE TABLE config_info_aggr ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - datum_id varchar(255) NOT NULL, - app_name varchar(128), - content CLOB, - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - constraint configinfoaggr_id_key PRIMARY KEY (id), - constraint uk_configinfoaggr_datagrouptenantdatum UNIQUE (data_id,group_id,tenant_id,datum_id)); +CREATE TABLE config_info_gray ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + gray_name varchar(128) NOT NULL, + gray_rule CLOB, + app_name varchar(128), + src_ip varchar(128), + src_user varchar(128) default '', + content CLOB, + md5 varchar(32) DEFAULT NULL, + encrypted_data_key varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + constraint configinfogray_id_key PRIMARY KEY (id), + constraint uk_configinfogray_datagrouptenantgrayname UNIQUE (data_id,group_id,tenant_id,gray_name)); +CREATE INDEX config_info_gray_dataid_gmt_modified ON config_info_gray(data_id,gmt_modified); +CREATE INDEX config_info_gray_gmt_modified ON config_info_gray(gmt_modified); CREATE TABLE app_list ( id bigint NOT NULL generated by default as identity, @@ -215,14 +225,15 @@ CREATE TABLE permissions ( /******************************************/ /* ipv6 support */ /******************************************/ -ALTER TABLE `config_info_tag` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `his_config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL AFTER `src_user`; +ALTER TABLE config_info_tag ADD src_ip varchar(50) DEFAULT NULL; + +ALTER TABLE his_config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info_beta ADD src_ip varchar(50) DEFAULT NULL ; -ALTER TABLE `config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `config_info_beta` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; \ No newline at end of file +ALTER TABLE his_config_info ADD publish_type varchar(50) DEFAULT 'formal'; +ALTER TABLE his_config_info ADD ext_info CLOB DEFAULT NULL ; diff --git a/console/src/main/resources/static/index.html b/console/src/main/resources/static/index.html index c91bfb03112..e1a9ee62483 100644 --- a/console/src/main/resources/static/index.html +++ b/console/src/main/resources/static/index.html @@ -35,7 +35,7 @@ - +
@@ -56,6 +56,6 @@ - + diff --git a/console/src/main/resources/static/js/main.js b/console/src/main/resources/static/js/main.js index d2f7b8d2379..149ed8d26d4 100644 --- a/console/src/main/resources/static/js/main.js +++ b/console/src/main/resources/static/js/main.js @@ -1,19 +1,19 @@ -!function(n){var a={};function r(e){var t;return(a[e]||(t=a[e]={i:e,l:!1,exports:{}},n[e].call(t.exports,t,t.exports,r),t.l=!0,t)).exports}r.m=n,r.c=a,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var a in t)r.d(n,a,function(e){return t[e]}.bind(null,a));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=462)}([function(e,t,n){"use strict";e.exports=n(469)},function(e,t,n){"use strict";n.d(t,"b",function(){return T}),n.d(t,"f",function(){return L}),n.d(t,"c",function(){return m}),n.d(t,"d",function(){return a}),n.d(t,"a",function(){return o}),n.d(t,"e",function(){return O});n(47);var t=n(24),c=n.n(t),l=n(76),r=n(94),d=n(62),f=n(32),t=n(111),u=n.n(t),t=n(68),p=n.n(t),h=n(22);function m(){var e=window.location.href,e=(localStorage.removeItem("token"),e.split("#")[0]);console.log("base_url",e),window.location="".concat(e,"#/login")}function a(){var e=window.location.href,e=(localStorage.removeItem("token"),e.split("#")[0]);window.location="".concat(e,"#/register")}function o(e){for(var t="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",n="",a=0;a>>0,a;for(a=0;a0)for(n=0;n=0;return(o?n?"+":"":"-")+Math.pow(10,Math.max(0,r)).toString().substr(1)+a}var ie=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,se=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,le={},ue={};function a(e,t,n,a){var r=a;if(typeof a==="string")r=function(){return this[a]()};if(e)ue[e]=r;if(t)ue[t[0]]=function(){return o(r.apply(this,arguments),t[1],t[2])};if(n)ue[n]=function(){return this.localeData().ordinal(r.apply(this,arguments),e)}}function ce(e){if(e.match(/\[[\s\S]/))return e.replace(/^\[|\]$/g,"");return e.replace(/\\/g,"")}function de(a){var r=a.match(ie),e,o;for(e=0,o=r.length;e=0&&se.test(e)){e=e.replace(se,a);se.lastIndex=0;n-=1}return e}var he={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function me(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];if(t||!n)return t;this._longDateFormat[e]=n.match(ie).map(function(e){if(e==="MMMM"||e==="MM"||e==="DD"||e==="dddd")return e.slice(1);return e}).join("");return this._longDateFormat[e]}var ge="Invalid date";function ye(){return this._invalidDate}var ve="%d",_e=/\d{1,2}/;function be(e){return this._ordinal.replace("%d",e)}var we={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function Me(e,t,n,a){var r=this._relativeTime[n];return h(r)?r(e,t,n,a):r.replace(/%d/i,e)}function ke(e,t){var n=this._relativeTime[e>0?"future":"past"];return h(n)?n(t):n.replace(/%s/i,t)}var Se={};function t(e,t){var n=e.toLowerCase();Se[n]=Se[n+"s"]=Se[t]=e}function m(e){return typeof e==="string"?Se[e]||Se[e.toLowerCase()]:undefined}function Ee(e){var t={},n,a;for(a in e)if(l(e,a)){n=m(a);if(n)t[n]=e[a]}return t}var xe={};function n(e,t){xe[e]=t}function Ce(e){var t=[],n;for(n in e)if(l(e,n))t.push({unit:n,priority:xe[n]});t.sort(function(e,t){return e.priority-t.priority});return t}function Te(e){return e%4===0&&e%100!==0||e%400===0}function g(e){if(e<0)return Math.ceil(e)||0;else return Math.floor(e)}function y(e){var t=+e,n=0;if(t!==0&&isFinite(t))n=g(t);return n}function Le(t,n){return function(e){if(e!=null){De(this,t,e);d.updateOffset(this,n);return this}else return Oe(this,t)}}function Oe(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function De(e,t,n){if(e.isValid()&&!isNaN(n))if(t==="FullYear"&&Te(e.year())&&e.month()===1&&e.date()===29){n=y(n);e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),ot(n,e.month()))}else e._d["set"+(e._isUTC?"UTC":"")+t](n)}function Ne(e){e=m(e);if(h(this[e]))return this[e]();return this}function Pe(e,t){if(typeof e==="object"){e=Ee(e);var n=Ce(e),a,r=n.length;for(a=0;a68?1900:2e3)};var Mt=Le("FullYear",true);function kt(){return Te(this.year())}function St(e,t,n,a,r,o,i){var s;if(e<100&&e>=0){s=new Date(e+400,t,n,a,r,o,i);if(isFinite(s.getFullYear()))s.setFullYear(e)}else s=new Date(e,t,n,a,r,o,i);return s}function Et(e){var t,n;if(e<100&&e>=0){n=Array.prototype.slice.call(arguments);n[0]=e+400;t=new Date(Date.UTC.apply(null,n));if(isFinite(t.getUTCFullYear()))t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function xt(e,t,n){var a=7+t-n,r=(7+Et(e,0,a).getUTCDay()-t)%7;return-r+a-1}function Ct(e,t,n,a,r){var o=(7+n-a)%7,i=xt(e,a,r),s=1+7*(t-1)+o+i,l,u;if(s<=0){l=e-1;u=wt(l)+s}else if(s>wt(e)){l=e+1;u=s-wt(e)}else{l=e;u=s}return{year:l,dayOfYear:u}}function Tt(e,t,n){var a=xt(e.year(),t,n),r=Math.floor((e.dayOfYear()-a-1)/7)+1,o,i;if(r<1){i=e.year()-1;o=r+L(i,t,n)}else if(r>L(e.year(),t,n)){o=r-L(e.year(),t,n);i=e.year()+1}else{i=e.year();o=r}return{week:o,year:i}}function L(e,t,n){var a=xt(e,t,n),r=xt(e+1,t,n);return(wt(e)-a+r)/7}function Lt(e){return Tt(e,this._week.dow,this._week.doy).week}a("w",["ww",2],"wo","week"),a("W",["WW",2],"Wo","isoWeek"),t("week","w"),t("isoWeek","W"),n("week",5),n("isoWeek",5),_("w",v),_("ww",v,r),_("W",v),_("WW",v,r),Ze(["w","ww","W","WW"],function(e,t,n,a){t[a.substr(0,1)]=y(e)});var Ot={dow:0,doy:6};function Dt(){return this._week.dow}function Nt(){return this._week.doy}function Pt(e){var t=this.localeData().week(this);return e==null?t:this.add((e-t)*7,"d")}function jt(e){var t=Tt(this,1,4).week;return e==null?t:this.add((e-t)*7,"d")}function Yt(e,t){if(typeof e!=="string")return e;if(!isNaN(e))return parseInt(e,10);e=t.weekdaysParse(e);if(typeof e==="number")return e;return null}function It(e,t){if(typeof e==="string")return t.weekdaysParse(e)%7||7;return isNaN(e)?null:e}function At(e,t){return e.slice(t,7).concat(e.slice(0,t))}a("d",0,"do","day"),a("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),a("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),a("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),a("e",0,0,"weekday"),a("E",0,0,"isoWeekday"),t("day","d"),t("weekday","e"),t("isoWeekday","E"),n("day",11),n("weekday",11),n("isoWeekday",11),_("d",v),_("e",v),_("E",v),_("dd",function(e,t){return t.weekdaysMinRegex(e)}),_("ddd",function(e,t){return t.weekdaysShortRegex(e)}),_("dddd",function(e,t){return t.weekdaysRegex(e)}),Ze(["dd","ddd","dddd"],function(e,t,n,a){var r=n._locale.weekdaysParse(e,a,n._strict);if(r!=null)t.d=r;else f(n).invalidWeekday=e}),Ze(["d","e","E"],function(e,t,n,a){t[a]=y(e)});var Rt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Ht="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Ft="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),zt=Ge,Wt=Ge,Bt=Ge;function Ut(e,t){var n=i(this._weekdays)?this._weekdays:this._weekdays[e&&e!==true&&this._weekdays.isFormat.test(t)?"format":"standalone"];return e===true?At(n,this._week.dow):e?n[e.day()]:n}function Vt(e){return e===true?At(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function Kt(e){return e===true?At(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function qt(e,t,n){var a,r,o,i=e.toLocaleLowerCase();if(!this._weekdaysParse){this._weekdaysParse=[];this._shortWeekdaysParse=[];this._minWeekdaysParse=[];for(a=0;a<7;++a){o=c([2e3,1]).day(a);this._minWeekdaysParse[a]=this.weekdaysMin(o,"").toLocaleLowerCase();this._shortWeekdaysParse[a]=this.weekdaysShort(o,"").toLocaleLowerCase();this._weekdaysParse[a]=this.weekdays(o,"").toLocaleLowerCase()}}if(n)if(t==="dddd"){r=T.call(this._weekdaysParse,i);return r!==-1?r:null}else if(t==="ddd"){r=T.call(this._shortWeekdaysParse,i);return r!==-1?r:null}else{r=T.call(this._minWeekdaysParse,i);return r!==-1?r:null}else if(t==="dddd"){r=T.call(this._weekdaysParse,i);if(r!==-1)return r;r=T.call(this._shortWeekdaysParse,i);if(r!==-1)return r;r=T.call(this._minWeekdaysParse,i);return r!==-1?r:null}else if(t==="ddd"){r=T.call(this._shortWeekdaysParse,i);if(r!==-1)return r;r=T.call(this._weekdaysParse,i);if(r!==-1)return r;r=T.call(this._minWeekdaysParse,i);return r!==-1?r:null}else{r=T.call(this._minWeekdaysParse,i);if(r!==-1)return r;r=T.call(this._weekdaysParse,i);if(r!==-1)return r;r=T.call(this._shortWeekdaysParse,i);return r!==-1?r:null}}function Gt(e,t,n){var a,r,o;if(this._weekdaysParseExact)return qt.call(this,e,t,n);if(!this._weekdaysParse){this._weekdaysParse=[];this._minWeekdaysParse=[];this._shortWeekdaysParse=[];this._fullWeekdaysParse=[]}for(a=0;a<7;a++){r=c([2e3,1]).day(a);if(n&&!this._fullWeekdaysParse[a]){this._fullWeekdaysParse[a]=new RegExp("^"+this.weekdays(r,"").replace(".","\\.?")+"$","i");this._shortWeekdaysParse[a]=new RegExp("^"+this.weekdaysShort(r,"").replace(".","\\.?")+"$","i");this._minWeekdaysParse[a]=new RegExp("^"+this.weekdaysMin(r,"").replace(".","\\.?")+"$","i")}if(!this._weekdaysParse[a]){o="^"+this.weekdays(r,"")+"|^"+this.weekdaysShort(r,"")+"|^"+this.weekdaysMin(r,"");this._weekdaysParse[a]=new RegExp(o.replace(".",""),"i")}if(n&&t==="dddd"&&this._fullWeekdaysParse[a].test(e))return a;else if(n&&t==="ddd"&&this._shortWeekdaysParse[a].test(e))return a;else if(n&&t==="dd"&&this._minWeekdaysParse[a].test(e))return a;else if(!n&&this._weekdaysParse[a].test(e))return a}}function $t(e){if(!this.isValid())return e!=null?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();if(e!=null){e=Yt(e,this.localeData());return this.add(e-t,"d")}else return t}function Jt(e){if(!this.isValid())return e!=null?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return e==null?t:this.add(e-t,"d")}function Qt(e){if(!this.isValid())return e!=null?this:NaN;if(e!=null){var t=It(e,this.localeData());return this.day(this.day()%7?t:t-7)}else return this.day()||7}function Xt(e){if(this._weekdaysParseExact){if(!l(this,"_weekdaysRegex"))tn.call(this);if(e)return this._weekdaysStrictRegex;else return this._weekdaysRegex}else{if(!l(this,"_weekdaysRegex"))this._weekdaysRegex=zt;return this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex}}function Zt(e){if(this._weekdaysParseExact){if(!l(this,"_weekdaysRegex"))tn.call(this);if(e)return this._weekdaysShortStrictRegex;else return this._weekdaysShortRegex}else{if(!l(this,"_weekdaysShortRegex"))this._weekdaysShortRegex=Wt;return this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex}}function en(e){if(this._weekdaysParseExact){if(!l(this,"_weekdaysRegex"))tn.call(this);if(e)return this._weekdaysMinStrictRegex;else return this._weekdaysMinRegex}else{if(!l(this,"_weekdaysMinRegex"))this._weekdaysMinRegex=Bt;return this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex}}function tn(){function e(e,t){return t.length-e.length}var t=[],n=[],a=[],r=[],o,i,s,l,u;for(o=0;o<7;o++){i=c([2e3,1]).day(o);s=b(this.weekdaysMin(i,""));l=b(this.weekdaysShort(i,""));u=b(this.weekdays(i,""));t.push(s);n.push(l);a.push(u);r.push(s);r.push(l);r.push(u)}t.sort(e);n.sort(e);a.sort(e);r.sort(e);this._weekdaysRegex=new RegExp("^("+r.join("|")+")","i");this._weekdaysShortRegex=this._weekdaysRegex;this._weekdaysMinRegex=this._weekdaysRegex;this._weekdaysStrictRegex=new RegExp("^("+a.join("|")+")","i");this._weekdaysShortStrictRegex=new RegExp("^("+n.join("|")+")","i");this._weekdaysMinStrictRegex=new RegExp("^("+t.join("|")+")","i")}function nn(){return this.hours()%12||12}function an(){return this.hours()||24}function rn(e,t){a(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function on(e,t){return t._meridiemParse}function sn(e){return(e+"").toLowerCase().charAt(0)==="p"}a("H",["HH",2],0,"hour"),a("h",["hh",2],0,nn),a("k",["kk",2],0,an),a("hmm",0,0,function(){return""+nn.apply(this)+o(this.minutes(),2)}),a("hmmss",0,0,function(){return""+nn.apply(this)+o(this.minutes(),2)+o(this.seconds(),2)}),a("Hmm",0,0,function(){return""+this.hours()+o(this.minutes(),2)}),a("Hmmss",0,0,function(){return""+this.hours()+o(this.minutes(),2)+o(this.seconds(),2)}),rn("a",true),rn("A",false),t("hour","h"),n("hour",13),_("a",on),_("A",on),_("H",v),_("h",v),_("k",v),_("HH",v,r),_("hh",v,r),_("kk",v,r),_("hmm",Re),_("hmmss",He),_("Hmm",Re),_("Hmmss",He),w(["H","HH"],E),w(["k","kk"],function(e,t,n){var a=y(e);t[E]=a===24?0:a}),w(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e);n._meridiem=e}),w(["h","hh"],function(e,t,n){t[E]=y(e);f(n).bigHour=true}),w("hmm",function(e,t,n){var a=e.length-2;t[E]=y(e.substr(0,a));t[x]=y(e.substr(a));f(n).bigHour=true}),w("hmmss",function(e,t,n){var a=e.length-4,r=e.length-2;t[E]=y(e.substr(0,a));t[x]=y(e.substr(a,2));t[C]=y(e.substr(r));f(n).bigHour=true}),w("Hmm",function(e,t,n){var a=e.length-2;t[E]=y(e.substr(0,a));t[x]=y(e.substr(a))}),w("Hmmss",function(e,t,n){var a=e.length-4,r=e.length-2;t[E]=y(e.substr(0,a));t[x]=y(e.substr(a,2));t[C]=y(e.substr(r))});var ln,un=Le("Hours",true);function cn(e,t,n){if(e>11)return n?"pm":"PM";else return n?"am":"AM"}var dn={calendar:re,longDateFormat:he,invalidDate:ge,ordinal:ve,dayOfMonthOrdinalParse:_e,relativeTime:we,months:it,monthsShort:st,week:Ot,weekdays:Rt,weekdaysMin:Ft,weekdaysShort:Ht,meridiemParse:/[ap]\.?m?\.?/i},O={},fn={},pn;function hn(e,t){var n,a=Math.min(e.length,t.length);for(n=0;n0){r=vn(o.slice(0,n).join("-"));if(r)return r;if(a&&a.length>=n&&hn(o,a)>=n-1)break;n--}t++}return pn}function yn(e){return e.match("^[^/\\\\]*$")!=null}function vn(t){var e=null,n;if(O[t]===undefined&&typeof ci!=="undefined"&&ci&&ci.exports&&yn(t))try{e=pn._abbr;n=di;fi(536)("./"+t);_n(e)}catch(e){O[t]=null}return O[t]}function _n(e,t){var n;if(e){if(s(t))n=Mn(e);else n=bn(e,t);if(n)pn=n;else if(typeof console!=="undefined"&&console.warn)console.warn("Locale "+e+" not found. Did you forget to load it?")}return pn._abbr}function bn(e,t){if(t!==null){var n,a=dn;t.abbr=e;if(O[e]!=null){ee("defineLocaleOverride","use moment.updateLocale(localeName, config) to change "+"an existing locale. moment.defineLocale(localeName, "+"config) should only be used for creating a new locale "+"See http://momentjs.com/guides/#/warnings/define-locale/ for more info.");a=O[e]._config}else if(t.parentLocale!=null)if(O[t.parentLocale]!=null)a=O[t.parentLocale]._config;else{n=vn(t.parentLocale);if(n!=null)a=n._config;else{if(!fn[t.parentLocale])fn[t.parentLocale]=[];fn[t.parentLocale].push({name:e,config:t});return null}}O[e]=new ae(ne(a,t));if(fn[e])fn[e].forEach(function(e){bn(e.name,e.config)});_n(e);return O[e]}else{delete O[e];return null}}function wn(e,t){if(t!=null){var n,a,r=dn;if(O[e]!=null&&O[e].parentLocale!=null)O[e].set(ne(O[e]._config,t));else{a=vn(e);if(a!=null)r=a._config;t=ne(r,t);if(a==null)t.abbr=e;n=new ae(t);n.parentLocale=O[e];O[e]=n}_n(e)}else if(O[e]!=null)if(O[e].parentLocale!=null){O[e]=O[e].parentLocale;if(e===_n())_n(e)}else if(O[e]!=null)delete O[e];return O[e]}function Mn(e){var t;if(e&&e._locale&&e._locale._abbr)e=e._locale._abbr;if(!e)return pn;if(!i(e)){t=vn(e);if(t)return t;e=[e]}return gn(e)}function kn(){return Z(O)}function Sn(e){var t,n=e._a;if(n&&f(e).overflow===-2){t=n[k]<0||n[k]>11?k:n[S]<1||n[S]>ot(n[M],n[k])?S:n[E]<0||n[E]>24||n[E]===24&&(n[x]!==0||n[C]!==0||n[tt]!==0)?E:n[x]<0||n[x]>59?x:n[C]<0||n[C]>59?C:n[tt]<0||n[tt]>999?tt:-1;if(f(e)._overflowDayOfYear&&(tS))t=S;if(f(e)._overflowWeeks&&t===-1)t=nt;if(f(e)._overflowWeekday&&t===-1)t=at;f(e).overflow=t}return e}var En=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,xn=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Cn=/Z|[+-]\d\d(?::?\d\d)?/,Tn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,false],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,false],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,false],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,false],["YYYY",/\d{4}/,false]],Ln=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],On=/^\/?Date\((-?\d+)/i,Dn=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Nn={UT:0,GMT:0,EDT:-4*60,EST:-5*60,CDT:-5*60,CST:-6*60,MDT:-6*60,MST:-7*60,PDT:-7*60,PST:-8*60};function Pn(e){var t,n,a=e._i,r=En.exec(a)||xn.exec(a),o,i,s,l,u=Tn.length,c=Ln.length;if(r){f(e).iso=true;for(t=0,n=u;twt(i)||e._dayOfYear===0)f(e)._overflowDayOfYear=true;n=Et(i,0,e._dayOfYear);e._a[k]=n.getUTCMonth();e._a[S]=n.getUTCDate()}for(t=0;t<3&&e._a[t]==null;++t)e._a[t]=a[t]=r[t];for(;t<7;t++)e._a[t]=a[t]=e._a[t]==null?t===2?1:0:e._a[t];if(e._a[E]===24&&e._a[x]===0&&e._a[C]===0&&e._a[tt]===0){e._nextDay=true;e._a[E]=0}e._d=(e._useUTC?Et:St).apply(null,a);o=e._useUTC?e._d.getUTCDay():e._d.getDay();if(e._tzm!=null)e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm);if(e._nextDay)e._a[E]=24;if(e._w&&typeof e._w.d!=="undefined"&&e._w.d!==o)f(e).weekdayMismatch=true}function Un(e){var t,n,a,r,o,i,s,l,u;t=e._w;if(t.GG!=null||t.W!=null||t.E!=null){o=1;i=4;n=zn(t.GG,e._a[M],Tt(D(),1,4).year);a=zn(t.W,1);r=zn(t.E,1);if(r<1||r>7)l=true}else{o=e._locale._week.dow;i=e._locale._week.doy;u=Tt(D(),o,i);n=zn(t.gg,e._a[M],u.year);a=zn(t.w,u.week);if(t.d!=null){r=t.d;if(r<0||r>6)l=true}else if(t.e!=null){r=t.e+o;if(t.e<0||t.e>6)l=true}else r=o}if(a<1||a>L(n,o,i))f(e)._overflowWeeks=true;else if(l!=null)f(e)._overflowWeekday=true;else{s=Ct(n,a,r,o,i);e._a[M]=s.year;e._dayOfYear=s.dayOfYear}}function Vn(e){if(e._f===d.ISO_8601){Pn(e);return}if(e._f===d.RFC_2822){Hn(e);return}e._a=[];f(e).empty=true;var t=""+e._i,n,a,r,o,i,s=t.length,l=0,u,c;r=pe(e._f,e._locale).match(ie)||[];c=r.length;for(n=0;n0)f(e).unusedInput.push(i);t=t.slice(t.indexOf(a)+a.length);l+=a.length}if(ue[o]){if(a)f(e).empty=false;else f(e).unusedTokens.push(o);et(o,a,e)}else if(e._strict&&!a)f(e).unusedTokens.push(o)}f(e).charsLeftOver=s-l;if(t.length>0)f(e).unusedInput.push(t);if(e._a[E]<=12&&f(e).bigHour===true&&e._a[E]>0)f(e).bigHour=undefined;f(e).parsedDateParts=e._a.slice(0);f(e).meridiem=e._meridiem;e._a[E]=Kn(e._locale,e._a[E],e._meridiem);u=f(e).era;if(u!==null)e._a[M]=e._locale.erasConvertYear(u,e._a[M]);Bn(e);Sn(e)}function Kn(e,t,n){var a;if(n==null)return t;if(e.meridiemHour!=null)return e.meridiemHour(t,n);else if(e.isPM!=null){a=e.isPM(n);if(a&&t<12)t+=12;if(!a&&t===12)t=0;return t}else return t}function qn(e){var t,n,a,r,o,i,s=false,l=e._f.length;if(l===0){f(e).invalidFormat=true;e._d=new Date(NaN);return}for(r=0;rthis?this:e;else return K()});function ta(e,t){var n,a;if(t.length===1&&i(t[0]))t=t[0];if(!t.length)return D();n=t[0];for(a=1;athis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ea(){if(!s(this._isDSTShifted))return this._isDSTShifted;var e={},t;$(e,this);e=Jn(e);if(e._a){t=e._isUTC?c(e._a):D(e._a);this._isDSTShifted=this.isValid()&&fa(e._a,t.toArray())>0}else this._isDSTShifted=false;return this._isDSTShifted}function xa(){return this.isValid()?!this._isUTC:false}function Ca(){return this.isValid()?this._isUTC:false}function Ta(){return this.isValid()?this._isUTC&&this._offset===0:false}d.updateOffset=function(){};var La=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Oa=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function N(e,t){var n=e,a=null,r,o,i;if(ca(e))n={ms:e._milliseconds,d:e._days,M:e._months};else if(u(e)||!isNaN(+e)){n={};if(t)n[t]=+e;else n.milliseconds=+e}else if(a=La.exec(e)){r=a[1]==="-"?-1:1;n={y:0,d:y(a[S])*r,h:y(a[E])*r,m:y(a[x])*r,s:y(a[C])*r,ms:y(da(a[tt]*1e3))*r}}else if(a=Oa.exec(e)){r=a[1]==="-"?-1:1;n={y:Da(a[2],r),M:Da(a[3],r),w:Da(a[4],r),d:Da(a[5],r),h:Da(a[6],r),m:Da(a[7],r),s:Da(a[8],r)}}else if(n==null)n={};else if(typeof n==="object"&&("from"in n||"to"in n)){i=Pa(D(n.from),D(n.to));n={};n.ms=i.milliseconds;n.M=i.months}o=new ua(n);if(ca(e)&&l(e,"_locale"))o._locale=e._locale;if(ca(e)&&l(e,"_isValid"))o._isValid=e._isValid;return o}function Da(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Na(e,t){var n={};n.months=t.month()-e.month()+(t.year()-e.year())*12;if(e.clone().add(n.months,"M").isAfter(t))--n.months;n.milliseconds=+t-+e.clone().add(n.months,"M");return n}function Pa(e,t){var n;if(!(e.isValid()&&t.isValid()))return{milliseconds:0,months:0};t=ga(t,e);if(e.isBefore(t))n=Na(e,t);else{n=Na(t,e);n.milliseconds=-n.milliseconds;n.months=-n.months}return n}function ja(r,o){return function(e,t){var n,a;if(t!==null&&!isNaN(+t)){ee(o,"moment()."+o+"(period, number) is deprecated. Please use moment()."+o+"(number, period). "+"See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.");a=e;e=t;t=a}n=N(e,t);Ya(this,n,r);return this}}function Ya(e,t,n,a){var r=t._milliseconds,o=da(t._days),i=da(t._months);if(!e.isValid())return;a=a==null?true:a;if(i)mt(e,Oe(e,"Month")+i*n);if(o)De(e,"Date",Oe(e,"Date")+o*n);if(r)e._d.setTime(e._d.valueOf()+r*n);if(a)d.updateOffset(e,o||i)}N.fn=ua.prototype,N.invalid=la;var Ia=ja(1,"add"),Aa=ja(-1,"subtract");function Ra(e){return typeof e==="string"||e instanceof String}function Ha(e){return p(e)||z(e)||Ra(e)||u(e)||za(e)||Fa(e)||e===null||e===undefined}function Fa(e){var t=H(e)&&!F(e),n=false,a=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],r,o,i=a.length;for(r=0;rn.valueOf();else return n.valueOf()9999)return fe(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ");if(h(Date.prototype.toISOString))if(t)return this.toDate().toISOString();else return new Date(this.valueOf()+this.utcOffset()*60*1e3).toISOString().replace("Z",fe(n,"Z"));return fe(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function nr(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="",n,a,r,o;if(!this.isLocal()){e=this.utcOffset()===0?"moment.utc":"moment.parseZone";t="Z"}n="["+e+'("]';a=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY";r="-MM-DD[T]HH:mm:ss.SSS";o=t+'[")]';return this.format(n+a+r+o)}function ar(e){if(!e)e=this.isUtc()?d.defaultFormatUtc:d.defaultFormat;var t=fe(this,e);return this.localeData().postformat(t)}function rr(e,t){if(this.isValid()&&(p(e)&&e.isValid()||D(e).isValid()))return N({to:this,from:e}).locale(this.locale()).humanize(!t);else return this.localeData().invalidDate()}function or(e){return this.from(D(),e)}function ir(e,t){if(this.isValid()&&(p(e)&&e.isValid()||D(e).isValid()))return N({from:this,to:e}).locale(this.locale()).humanize(!t);else return this.localeData().invalidDate()}function sr(e){return this.to(D(),e)}function lr(e){var t;if(e===undefined)return this._locale._abbr;else{t=Mn(e);if(t!=null)this._locale=t;return this}}d.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",d.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var ur=e("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){if(e===undefined)return this.localeData();else return this.locale(e)});function cr(){return this._locale}var dr=1e3,fr=60*dr,pr=60*fr,hr=(365*400+97)*24*pr;function mr(e,t){return(e%t+t)%t}function gr(e,t,n){if(e<100&&e>=0)return new Date(e+400,t,n)-hr;else return new Date(e,t,n).valueOf()}function yr(e,t,n){if(e<100&&e>=0)return Date.UTC(e+400,t,n)-hr;else return Date.UTC(e,t,n)}function vr(e){var t,n;e=m(e);if(e===undefined||e==="millisecond"||!this.isValid())return this;n=this._isUTC?yr:gr;switch(e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf();t-=mr(t+(this._isUTC?0:this.utcOffset()*fr),pr);break;case"minute":t=this._d.valueOf();t-=mr(t,fr);break;case"second":t=this._d.valueOf();t-=mr(t,dr);break}this._d.setTime(t);d.updateOffset(this,true);return this}function _r(e){var t,n;e=m(e);if(e===undefined||e==="millisecond"||!this.isValid())return this;n=this._isUTC?yr:gr;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf();t+=pr-mr(t+(this._isUTC?0:this.utcOffset()*fr),pr)-1;break;case"minute":t=this._d.valueOf();t+=fr-mr(t,fr)-1;break;case"second":t=this._d.valueOf();t+=dr-mr(t,dr)-1;break}this._d.setTime(t);d.updateOffset(this,true);return this}function br(){return this._d.valueOf()-(this._offset||0)*6e4}function wr(){return Math.floor(this.valueOf()/1e3)}function Mr(){return new Date(this.valueOf())}function kr(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function Sr(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function Er(){return this.isValid()?this.toISOString():null}function xr(){return V(this)}function Cr(){return B({},f(this))}function Tr(){return f(this).overflow}function Lr(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Or(e,t){var n,a,r,o=this._eras||Mn("en")._eras;for(n=0,a=o.length;n=0)return o[a]}}function Nr(e,t){var n=e.since<=e.until?+1:-1;if(t===undefined)return d(e.since).year();else return d(e.since).year()+(t-e.offset)*n}function Pr(){var e,t,n,a=this.localeData().eras();for(e=0,t=a.length;eo)t=o;return Zr.call(this,e,t,n,a,r)}}function Zr(e,t,n,a,r){var o=Ct(e,t,n,a,r),i=Et(o.year,0,o.dayOfYear);this.year(i.getUTCFullYear());this.month(i.getUTCMonth());this.date(i.getUTCDate());return this}function eo(e){return e==null?Math.ceil((this.month()+1)/3):this.month((e-1)*3+this.month()%3)}a("N",0,0,"eraAbbr"),a("NN",0,0,"eraAbbr"),a("NNN",0,0,"eraAbbr"),a("NNNN",0,0,"eraName"),a("NNNNN",0,0,"eraNarrow"),a("y",["y",1],"yo","eraYear"),a("y",["yy",2],0,"eraYear"),a("y",["yyy",3],0,"eraYear"),a("y",["yyyy",4],0,"eraYear"),_("N",Fr),_("NN",Fr),_("NNN",Fr),_("NNNN",zr),_("NNNNN",Wr),w(["N","NN","NNN","NNNN","NNNNN"],function(e,t,n,a){var r=n._locale.erasParse(e,a,n._strict);if(r)f(n).era=r;else f(n).invalidEra=e}),_("y",Be),_("yy",Be),_("yyy",Be),_("yyyy",Be),_("yo",Br),w(["y","yy","yyy","yyyy"],M),w(["yo"],function(e,t,n,a){var r;if(n._locale._eraYearOrdinalRegex)r=e.match(n._locale._eraYearOrdinalRegex);if(n._locale.eraYearOrdinalParse)t[M]=n._locale.eraYearOrdinalParse(e,r);else t[M]=parseInt(e,10)}),a(0,["gg",2],0,function(){return this.weekYear()%100}),a(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Vr("gggg","weekYear"),Vr("ggggg","weekYear"),Vr("GGGG","isoWeekYear"),Vr("GGGGG","isoWeekYear"),t("weekYear","gg"),t("isoWeekYear","GG"),n("weekYear",1),n("isoWeekYear",1),_("G",Ue),_("g",Ue),_("GG",v,r),_("gg",v,r),_("GGGG",ze,Ie),_("gggg",ze,Ie),_("GGGGG",We,Ae),_("ggggg",We,Ae),Ze(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,a){t[a.substr(0,2)]=y(e)}),Ze(["gg","GG"],function(e,t,n,a){t[a]=d.parseTwoDigitYear(e)}),a("Q",0,"Qo","quarter"),t("quarter","Q"),n("quarter",7),_("Q",je),w("Q",function(e,t){t[k]=(y(e)-1)*3}),a("D",["DD",2],"Do","date"),t("date","D"),n("date",9),_("D",v),_("DD",v,r),_("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),w(["D","DD"],S),w("Do",function(e,t){t[S]=y(e.match(v)[0])});var to=Le("Date",true);function no(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return e==null?t:this.add(e-t,"d")}a("DDD",["DDDD",3],"DDDo","dayOfYear"),t("dayOfYear","DDD"),n("dayOfYear",4),_("DDD",Fe),_("DDDD",Ye),w(["DDD","DDDD"],function(e,t,n){n._dayOfYear=y(e)}),a("m",["mm",2],0,"minute"),t("minute","m"),n("minute",14),_("m",v),_("mm",v,r),w(["m","mm"],x);var ao=Le("Minutes",false),ro=(a("s",["ss",2],0,"second"),t("second","s"),n("second",15),_("s",v),_("ss",v,r),w(["s","ss"],C),Le("Seconds",false)),oo,io;for(a("S",0,0,function(){return~~(this.millisecond()/100)}),a(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),a(0,["SSS",3],0,"millisecond"),a(0,["SSSS",4],0,function(){return this.millisecond()*10}),a(0,["SSSSS",5],0,function(){return this.millisecond()*100}),a(0,["SSSSSS",6],0,function(){return this.millisecond()*1e3}),a(0,["SSSSSSS",7],0,function(){return this.millisecond()*1e4}),a(0,["SSSSSSSS",8],0,function(){return this.millisecond()*1e5}),a(0,["SSSSSSSSS",9],0,function(){return this.millisecond()*1e6}),t("millisecond","ms"),n("millisecond",16),_("S",Fe,je),_("SS",Fe,r),_("SSS",Fe,Ye),oo="SSSS";oo.length<=9;oo+="S")_(oo,Be);function so(e,t){t[tt]=y(("0."+e)*1e3)}for(oo="S";oo.length<=9;oo+="S")w(oo,so);function lo(){return this._isUTC?"UTC":""}function uo(){return this._isUTC?"Coordinated Universal Time":""}io=Le("Milliseconds",false),a("z",0,0,"zoneAbbr"),a("zz",0,0,"zoneName");var P=J.prototype;if(P.add=Ia,P.calendar=Ua,P.clone=Va,P.diff=Xa,P.endOf=_r,P.format=ar,P.from=rr,P.fromNow=or,P.to=ir,P.toNow=sr,P.get=Ne,P.invalidAt=Tr,P.isAfter=Ka,P.isBefore=qa,P.isBetween=Ga,P.isSame=$a,P.isSameOrAfter=Ja,P.isSameOrBefore=Qa,P.isValid=xr,P.lang=ur,P.locale=lr,P.localeData=cr,P.max=ea,P.min=Zn,P.parsingFlags=Cr,P.set=Pe,P.startOf=vr,P.subtract=Aa,P.toArray=kr,P.toObject=Sr,P.toDate=Mr,P.toISOString=tr,P.inspect=nr,typeof Symbol!=="undefined"&&Symbol.for!=null)P[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"};function co(e){return D(e*1e3)}function fo(){return D.apply(null,arguments).parseZone()}function po(e){return e}P.toJSON=Er,P.toString=er,P.unix=wr,P.valueOf=br,P.creationData=Lr,P.eraName=Pr,P.eraNarrow=jr,P.eraAbbr=Yr,P.eraYear=Ir,P.year=Mt,P.isLeapYear=kt,P.weekYear=Kr,P.isoWeekYear=qr,P.quarter=P.quarters=eo,P.month=gt,P.daysInMonth=yt,P.week=P.weeks=Pt,P.isoWeek=P.isoWeeks=jt,P.weeksInYear=Jr,P.weeksInWeekYear=Qr,P.isoWeeksInYear=Gr,P.isoWeeksInISOWeekYear=$r,P.date=to,P.day=P.days=$t,P.weekday=Jt,P.isoWeekday=Qt,P.dayOfYear=no,P.hour=P.hours=un,P.minute=P.minutes=ao,P.second=P.seconds=ro,P.millisecond=P.milliseconds=io,P.utcOffset=va,P.utc=ba,P.local=wa,P.parseZone=Ma,P.hasAlignedHourOffset=ka,P.isDST=Sa,P.isLocal=xa,P.isUtcOffset=Ca,P.isUtc=Ta,P.isUTC=Ta,P.zoneAbbr=lo,P.zoneName=uo,P.dates=e("dates accessor is deprecated. Use date instead.",to),P.months=e("months accessor is deprecated. Use month instead",gt),P.years=e("years accessor is deprecated. Use year instead",Mt),P.zone=e("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",_a),P.isDSTShifted=e("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ea);var j=ae.prototype;function ho(e,t,n,a){var r=Mn(),o=c().set(a,t);return r[n](o,e)}function mo(e,t,n){if(u(e)){t=e;e=undefined}e=e||"";if(t!=null)return ho(e,t,n,"month");var a,r=[];for(a=0;a<12;a++)r[a]=ho(e,a,n,"month");return r}function go(e,t,n,a){if(typeof e==="boolean"){if(u(t)){n=t;t=undefined}t=t||""}else{t=e;n=t;e=false;if(u(t)){n=t;t=undefined}t=t||""}var r=Mn(),o=e?r._week.dow:0,i,s=[];if(n!=null)return ho(t,(n+o)%7,a,"day");for(i=0;i<7;i++)s[i]=ho(t,(i+o)%7,a,"day");return s}function yo(e,t){return mo(e,t,"months")}function vo(e,t){return mo(e,t,"monthsShort")}function _o(e,t,n){return go(e,t,n,"weekdays")}function bo(e,t,n){return go(e,t,n,"weekdaysShort")}function wo(e,t,n){return go(e,t,n,"weekdaysMin")}j.calendar=oe,j.longDateFormat=me,j.invalidDate=ye,j.ordinal=be,j.preparse=po,j.postformat=po,j.relativeTime=Me,j.pastFuture=ke,j.set=te,j.eras=Or,j.erasParse=Dr,j.erasConvertYear=Nr,j.erasAbbrRegex=Rr,j.erasNameRegex=Ar,j.erasNarrowRegex=Hr,j.months=dt,j.monthsShort=ft,j.monthsParse=ht,j.monthsRegex=_t,j.monthsShortRegex=vt,j.week=Lt,j.firstDayOfYear=Nt,j.firstDayOfWeek=Dt,j.weekdays=Ut,j.weekdaysMin=Kt,j.weekdaysShort=Vt,j.weekdaysParse=Gt,j.weekdaysRegex=Xt,j.weekdaysShortRegex=Zt,j.weekdaysMinRegex=en,j.isPM=sn,j.meridiem=cn,_n("en",{eras:[{since:"0001-01-01",until:+Infinity,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-Infinity,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10,n=y(e%100/10)===1?"th":t===1?"st":t===2?"nd":t===3?"rd":"th";return e+n}}),d.lang=e("moment.lang is deprecated. Use moment.locale instead.",_n),d.langData=e("moment.langData is deprecated. Use moment.localeData instead.",Mn);var Mo=Math.abs;function ko(){var e=this._data;this._milliseconds=Mo(this._milliseconds);this._days=Mo(this._days);this._months=Mo(this._months);e.milliseconds=Mo(e.milliseconds);e.seconds=Mo(e.seconds);e.minutes=Mo(e.minutes);e.hours=Mo(e.hours);e.months=Mo(e.months);e.years=Mo(e.years);return this}function So(e,t,n,a){var r=N(t,n);e._milliseconds+=a*r._milliseconds;e._days+=a*r._days;e._months+=a*r._months;return e._bubble()}function Eo(e,t){return So(this,e,t,1)}function xo(e,t){return So(this,e,t,-1)}function Co(e){if(e<0)return Math.floor(e);else return Math.ceil(e)}function To(){var e=this._milliseconds,t=this._days,n=this._months,a=this._data,r,o,i,s,l;if(!(e>=0&&t>=0&&n>=0||e<=0&&t<=0&&n<=0)){e+=Co(Oo(n)+t)*864e5;t=0;n=0}a.milliseconds=e%1e3;r=g(e/1e3);a.seconds=r%60;o=g(r/60);a.minutes=o%60;i=g(o/60);a.hours=i%24;t+=g(i/24);l=g(Lo(t));n+=l;t-=Co(Oo(l));s=g(n/12);n%=12;a.days=t;a.months=n;a.years=s;return this}function Lo(e){return e*4800/146097}function Oo(e){return e*146097/4800}function Do(e){if(!this.isValid())return NaN;var t,n,a=this._milliseconds;e=m(e);if(e==="month"||e==="quarter"||e==="year"){t=this._days+a/864e5;n=this._months+Lo(t);switch(e){case"month":return n;case"quarter":return n/3;case"year":return n/12}}else{t=this._days+Math.round(Oo(this._months));switch(e){case"week":return t/7+a/6048e5;case"day":return t+a/864e5;case"hour":return t*24+a/36e5;case"minute":return t*1440+a/6e4;case"second":return t*86400+a/1e3;case"millisecond":return Math.floor(t*864e5)+a;default:throw new Error("Unknown unit "+e)}}}function No(){if(!this.isValid())return NaN;return this._milliseconds+this._days*864e5+this._months%12*2592e6+y(this._months/12)*31536e6}function Po(e){return function(){return this.as(e)}}var jo=Po("ms"),Yo=Po("s"),Io=Po("m"),Ao=Po("h"),Ro=Po("d"),Ho=Po("w"),Fo=Po("M"),zo=Po("Q"),Wo=Po("y");function Bo(){return N(this)}function Uo(e){e=m(e);return this.isValid()?this[e+"s"]():NaN}function Vo(e){return function(){return this.isValid()?this._data[e]:NaN}}var Ko=Vo("milliseconds"),qo=Vo("seconds"),Go=Vo("minutes"),$o=Vo("hours"),Jo=Vo("days"),Qo=Vo("months"),Xo=Vo("years");function Zo(){return g(this.days()/7)}var ei=Math.round,ti={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function ni(e,t,n,a,r){return r.relativeTime(t||1,!!n,e,a)}function ai(e,t,n,a){var r=N(e).abs(),o=ei(r.as("s")),i=ei(r.as("m")),s=ei(r.as("h")),l=ei(r.as("d")),u=ei(r.as("M")),c=ei(r.as("w")),d=ei(r.as("y")),f=o<=n.ss&&["s",o]||o0;f[4]=a;return ni.apply(null,f)}function ri(e){if(e===undefined)return ei;if(typeof e==="function"){ei=e;return true}return false}function oi(e,t){if(ti[e]===undefined)return false;if(t===undefined)return ti[e];ti[e]=t;if(e==="s")ti.ss=t-1;return true}function ii(e,t){if(!this.isValid())return this.localeData().invalidDate();var n=false,a=ti,r,o;if(typeof e==="object"){t=e;e=false}if(typeof e==="boolean")n=e;if(typeof t==="object"){a=Object.assign({},ti,t);if(t.s!=null&&t.ss==null)a.ss=t.s-1}r=this.localeData();o=ai(this,!n,a,r);if(n)o=r.pastFuture(+this,o);return r.postformat(o)}var si=Math.abs;function li(e){return(e>0)-(e<0)||+e}function ui(){if(!this.isValid())return this.localeData().invalidDate();var e=si(this._milliseconds)/1e3,t=si(this._days),n=si(this._months),a,r,o,i,s=this.asSeconds(),l,u,c,d;if(!s)return"P0D";a=g(e/60);r=g(a/60);e%=60;a%=60;o=g(n/12);n%=12;i=e?e.toFixed(3).replace(/\.?0+$/,""):"";l=s<0?"-":"";u=li(this._months)!==li(s)?"-":"";c=li(this._days)!==li(s)?"-":"";d=li(this._milliseconds)!==li(s)?"-":"";return l+"P"+(o?u+o+"Y":"")+(n?u+n+"M":"")+(t?c+t+"D":"")+(r||a||e?"T":"")+(r?d+r+"H":"")+(a?d+a+"M":"")+(e?d+i+"S":"")}var Y=ua.prototype;return Y.isValid=sa,Y.abs=ko,Y.add=Eo,Y.subtract=xo,Y.as=Do,Y.asMilliseconds=jo,Y.asSeconds=Yo,Y.asMinutes=Io,Y.asHours=Ao,Y.asDays=Ro,Y.asWeeks=Ho,Y.asMonths=Fo,Y.asQuarters=zo,Y.asYears=Wo,Y.valueOf=No,Y._bubble=To,Y.clone=Bo,Y.get=Uo,Y.milliseconds=Ko,Y.seconds=qo,Y.minutes=Go,Y.hours=$o,Y.days=Jo,Y.weeks=Zo,Y.months=Qo,Y.years=Xo,Y.humanize=ii,Y.toISOString=ui,Y.toString=ui,Y.toJSON=ui,Y.locale=lr,Y.localeData=cr,Y.toIsoString=e("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ui),Y.lang=ur,a("X",0,0,"unix"),a("x",0,0,"valueOf"),_("x",Ue),_("X",qe),w("X",function(e,t,n){n._d=new Date(parseFloat(e)*1e3)}),w("x",function(e,t,n){n._d=new Date(y(e))}), //! moment.js -d.version="2.29.4",R(D),d.fn=P,d.min=na,d.max=aa,d.now=ra,d.utc=c,d.unix=co,d.months=yo,d.isDate=z,d.locale=_n,d.invalid=K,d.duration=N,d.isMoment=p,d.weekdays=_o,d.parseZone=fo,d.localeData=Mn,d.isDuration=ca,d.monthsShort=vo,d.weekdaysMin=wo,d.defineLocale=bn,d.updateLocale=wn,d.locales=kn,d.weekdaysShort=bo,d.normalizeUnits=m,d.relativeTimeRounding=ri,d.relativeTimeThreshold=oi,d.calendarFormat=Ba,d.prototype=P,d.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},d}()}.call(this,fi(535)(e))},function(e,t,n){"use strict";t.__esModule=!0;var a=u(n(3)),r=u(n(16)),o=u(n(6)),i=u(n(373)),s=u(n(601)),l=u(n(602)),n=u(n(375));function u(e){return e&&e.__esModule?e:{default:e}}i.default.Password=o.default.config(s.default,{exportNames:["getInputNode","focus"],transform:function(e,t){var n;return"hasLimitHint"in e&&(t("hasLimitHint","showLimitHint","Input"),n=(t=e).hasLimitHint,t=(0,r.default)(t,["hasLimitHint"]),e=(0,a.default)({showLimitHint:n},t)),e}}),i.default.TextArea=o.default.config(l.default,{exportNames:["getInputNode","focus"],transform:function(e,t){var n;return"hasLimitHint"in e&&(t("hasLimitHint","showLimitHint","Input"),n=(t=e).hasLimitHint,t=(0,r.default)(t,["hasLimitHint"]),e=(0,a.default)({showLimitHint:n},t)),e}}),i.default.Group=n.default,t.default=o.default.config(i.default,{exportNames:["getInputNode","focus"],transform:function(e,t){var n;return"hasLimitHint"in e&&(t("hasLimitHint","showLimitHint","Input"),n=(t=e).hasLimitHint,t=(0,r.default)(t,["hasLimitHint"]),e=(0,a.default)({showLimitHint:n},t)),e}}),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.pickAttrs=t.datejs=t.htmlId=t.KEYCODE=t.guid=t.focus=t.support=t.str=t.obj=t.log=t.func=t.events=t.env=t.dom=void 0;var a=y(n(215)),r=y(n(218)),o=y(n(518)),i=y(n(519)),s=y(n(217)),l=y(n(101)),u=y(n(216)),c=y(n(527)),d=y(n(528)),f=y(n(529)),p=g(n(530)),h=g(n(220)),m=g(n(164)),n=g(n(531));function g(e){return e&&e.__esModule?e:{default:e}}function y(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}t.dom=a,t.env=r,t.events=o,t.func=i,t.log=s,t.obj=l,t.str=u,t.support=c,t.focus=d,t.guid=p.default,t.KEYCODE=h.default,t.htmlId=f,t.datejs=m.default,t.pickAttrs=n.default},function(e,t,n){"use strict";function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}n.d(t,"a",function(){return a})},function(e,t,n){"use strict";function a(e,t){for(var n=0;n")),"shouldUpdatePosition"in r&&(delete t.shouldUpdatePosition,c.log.warning("Warning: [ shouldUpdatePosition ] is deprecated at [ ]")),"minMargin"in r&&o("minMargin","top/bottom",""),"isFullScreen"in r&&(r.overFlowScroll=!r.isFullScreen,delete t.isFullScreen,o("isFullScreen","overFlowScroll","")),t):(["target","offset","beforeOpen","onOpen","afterOpen","beforePosition","onPosition","cache","safeNode","wrapperClassName","container"].forEach(function(e){var t,n,a;e in r&&(o(e,"overlayProps."+e,"Dialog"),t=(n=r).overlayProps,n=(0,s.default)(n,["overlayProps"]),a=(0,i.default)(((a={})[e]=r[e],a),t||{}),delete n[e],r=(0,i.default)({overlayProps:a},n))}),r)}n.displayName="Dialog",n.Inner=p.default,n.show=function(e){return!1!==u.default.getContextProps(e,"Dialog").warning&&(e=v(e,c.log.deprecated)),(0,h.show)(e)},n.alert=function(e){return!1!==u.default.getContextProps(e,"Dialog").warning&&(e=v(e,c.log.deprecated)),(0,h.alert)(e)},n.confirm=function(e){return!1!==u.default.getContextProps(e,"Dialog").warning&&(e=v(e,c.log.deprecated)),(0,h.confirm)(e)},n.success=function(e){return(0,h.success)(e)},n.error=function(e){return(0,h.error)(e)},n.notice=function(e){return(0,h.notice)(e)},n.warning=function(e){return(0,h.warning)(e)},n.help=function(e){return(0,h.help)(e)},n.withContext=h.withContext,t.default=u.default.config(n,{transform:v}),e.exports=t.default},function(e,t,n){var a; +d.version="2.29.4",R(D),d.fn=P,d.min=na,d.max=aa,d.now=ra,d.utc=c,d.unix=co,d.months=yo,d.isDate=z,d.locale=_n,d.invalid=K,d.duration=N,d.isMoment=p,d.weekdays=_o,d.parseZone=fo,d.localeData=Mn,d.isDuration=ca,d.monthsShort=vo,d.weekdaysMin=wo,d.defineLocale=bn,d.updateLocale=wn,d.locales=kn,d.weekdaysShort=bo,d.normalizeUnits=m,d.relativeTimeRounding=ri,d.relativeTimeThreshold=oi,d.calendarFormat=Ba,d.prototype=P,d.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},d}()}.call(this,fi(535)(e))},function(e,t,n){"use strict";t.__esModule=!0;var a=u(n(3)),r=u(n(17)),o=u(n(6)),i=u(n(373)),s=u(n(601)),l=u(n(602)),n=u(n(375));function u(e){return e&&e.__esModule?e:{default:e}}i.default.Password=o.default.config(s.default,{exportNames:["getInputNode","focus"],transform:function(e,t){var n;return"hasLimitHint"in e&&(t("hasLimitHint","showLimitHint","Input"),n=(t=e).hasLimitHint,t=(0,r.default)(t,["hasLimitHint"]),e=(0,a.default)({showLimitHint:n},t)),e}}),i.default.TextArea=o.default.config(l.default,{exportNames:["getInputNode","focus"],transform:function(e,t){var n;return"hasLimitHint"in e&&(t("hasLimitHint","showLimitHint","Input"),n=(t=e).hasLimitHint,t=(0,r.default)(t,["hasLimitHint"]),e=(0,a.default)({showLimitHint:n},t)),e}}),i.default.Group=n.default,t.default=o.default.config(i.default,{exportNames:["getInputNode","focus"],transform:function(e,t){var n;return"hasLimitHint"in e&&(t("hasLimitHint","showLimitHint","Input"),n=(t=e).hasLimitHint,t=(0,r.default)(t,["hasLimitHint"]),e=(0,a.default)({showLimitHint:n},t)),e}}),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.pickAttrs=t.datejs=t.htmlId=t.KEYCODE=t.guid=t.focus=t.support=t.str=t.obj=t.log=t.func=t.events=t.env=t.dom=void 0;var a=y(n(215)),r=y(n(218)),o=y(n(518)),i=y(n(519)),s=y(n(217)),l=y(n(101)),u=y(n(216)),c=y(n(527)),d=y(n(528)),f=y(n(529)),p=g(n(530)),h=g(n(220)),m=g(n(164)),n=g(n(531));function g(e){return e&&e.__esModule?e:{default:e}}function y(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}t.dom=a,t.env=r,t.events=o,t.func=i,t.log=s,t.obj=l,t.str=u,t.support=c,t.focus=d,t.guid=p.default,t.KEYCODE=h.default,t.htmlId=f,t.datejs=m.default,t.pickAttrs=n.default},function(e,t,n){"use strict";n.d(t,"a",function(){return o});var a=n(94);function r(t,e){var n,a=Object.keys(t);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(t),e&&(n=n.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),a.push.apply(a,n)),a}function o(t){for(var e=1;e")),"shouldUpdatePosition"in r&&(delete t.shouldUpdatePosition,c.log.warning("Warning: [ shouldUpdatePosition ] is deprecated at [ ]")),"minMargin"in r&&o("minMargin","top/bottom",""),"isFullScreen"in r&&(r.overFlowScroll=!r.isFullScreen,delete t.isFullScreen,o("isFullScreen","overFlowScroll","")),t):(["target","offset","beforeOpen","onOpen","afterOpen","beforePosition","onPosition","cache","safeNode","wrapperClassName","container"].forEach(function(e){var t,n,a;e in r&&(o(e,"overlayProps."+e,"Dialog"),t=(n=r).overlayProps,n=(0,s.default)(n,["overlayProps"]),a=(0,i.default)(((a={})[e]=r[e],a),t||{}),delete n[e],r=(0,i.default)({overlayProps:a},n))}),r)}n.displayName="Dialog",n.Inner=p.default,n.show=function(e){return!1!==u.default.getContextProps(e,"Dialog").warning&&(e=v(e,c.log.deprecated)),(0,h.show)(e)},n.alert=function(e){return!1!==u.default.getContextProps(e,"Dialog").warning&&(e=v(e,c.log.deprecated)),(0,h.alert)(e)},n.confirm=function(e){return!1!==u.default.getContextProps(e,"Dialog").warning&&(e=v(e,c.log.deprecated)),(0,h.confirm)(e)},n.success=function(e){return(0,h.success)(e)},n.error=function(e){return(0,h.error)(e)},n.notice=function(e){return(0,h.notice)(e)},n.warning=function(e){return(0,h.warning)(e)},n.help=function(e){return(0,h.help)(e)},n.withContext=h.withContext,t.default=u.default.config(n,{transform:v}),e.exports=t.default},function(e,t,n){var a; /*! Copyright (c) 2018 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames */ -!function(){"use strict";var i={}.hasOwnProperty;function s(){for(var e=[],t=0;t 16.8.0")},p.prototype.validate=function(e,t){this.validateCallback(e,t)},p.prototype.reset=function(e){var t=1","Select");t=l(e,t);return e.onInputUpdate&&(t.onSearch=e.onInputUpdate,t.showSearch=!0),t}}),t.default=a.default.config(r.default,{transform:l,exportNames:["focusInput","handleSearchClear"]}),e.exports=t.default},function(M,e,t){"use strict";t.d(e,"a",function(){return a}),t.d(e,"b",function(){return U});var x=t(0),C=t.n(x),c=C.a.createContext(null);function l(){return n}var n=function(e){e()};var r={notify:function(){},get:function(){return[]}};function T(t,n){var o,i=r;function s(){e.onStateChange&&e.onStateChange()}function a(){var e,a,r;o||(o=n?n.addNestedSub(s):t.subscribe(s),e=l(),r=a=null,i={clear:function(){r=a=null},notify:function(){e(function(){for(var e=a;e;)e.callback(),e=e.next})},get:function(){for(var e=[],t=a;t;)e.push(t),t=t.next;return e},subscribe:function(e){var t=!0,n=r={callback:e,next:null,prev:r};return n.prev?n.prev.next=n:a=n,function(){t&&null!==a&&(t=!1,n.next?n.next.prev=n.prev:r=n.prev,n.prev?n.prev.next=n.next:a=n.next)}}})}var e={addNestedSub:function(e){return a(),i.subscribe(e)},notifyNestedSubs:function(){i.notify()},handleChangeWrapper:s,isSubscribed:function(){return Boolean(o)},trySubscribe:a,tryUnsubscribe:function(){o&&(o(),o=void 0,i.clear(),i=r)},getListeners:function(){return i}};return e}var o="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?x.useLayoutEffect:x.useEffect;var a=function(e){var t=e.store,n=e.context,e=e.children,a=Object(x.useMemo)(function(){var e=T(t);return{store:t,subscription:e}},[t]),r=Object(x.useMemo)(function(){return t.getState()},[t]),n=(o(function(){var e=a.subscription;return e.onStateChange=e.notifyNestedSubs,e.trySubscribe(),r!==t.getState()&&e.notifyNestedSubs(),function(){e.tryUnsubscribe(),e.onStateChange=null}},[a,r]),n||c);return C.a.createElement(n.Provider,{value:a},e)},L=t(41),O=t(56),e=t(107),d=t.n(e),D=t(430),f=["getDisplayName","methodName","renderCountProp","shouldHandleStateChanges","storeKey","withRef","forwardRef","context"],N=["reactReduxForwardedRef"],P=[],j=[null,null];function Y(e,t){e=e[1];return[t.payload,e+1]}function I(e,t,n){o(function(){return e.apply(void 0,t)},n)}function A(e,t,n,a,r,o,i){e.current=a,t.current=r,n.current=!1,o.current&&(o.current=null,i())}function R(e,a,t,r,o,i,s,l,u,c){var d,f;if(e)return d=!1,f=null,t.onStateChange=e=function(){if(!d){var e,t,n=a.getState();try{e=r(n,o.current)}catch(e){f=t=e}t||(f=null),e===i.current?s.current||u():(i.current=e,l.current=e,s.current=!0,c({type:"STORE_UPDATED",payload:{error:t}}))}},t.trySubscribe(),e(),function(){if(d=!0,t.tryUnsubscribe(),t.onStateChange=null,f)throw f}}var H=function(){return[null,0]};function i(k,e){var e=e=void 0===e?{}:e,t=e.getDisplayName,r=void 0===t?function(e){return"ConnectAdvanced("+e+")"}:t,t=e.methodName,o=void 0===t?"connectAdvanced":t,t=e.renderCountProp,i=void 0===t?void 0:t,t=e.shouldHandleStateChanges,S=void 0===t||t,t=e.storeKey,s=void 0===t?"store":t,t=(e.withRef,e.forwardRef),l=void 0!==t&&t,t=e.context,t=void 0===t?c:t,u=Object(O.a)(e,f),E=t;return function(b){var e=b.displayName||b.name||"Component",t=r(e),w=Object(L.a)({},u,{getDisplayName:r,methodName:o,renderCountProp:i,shouldHandleStateChanges:S,storeKey:s,displayName:t,wrappedComponentName:e,WrappedComponent:b}),e=u.pure;var M=e?x.useMemo:function(e){return e()};function n(n){var e=Object(x.useMemo)(function(){var e=n.reactReduxForwardedRef,t=Object(O.a)(n,N);return[n.context,e,t]},[n]),t=e[0],a=e[1],r=e[2],o=Object(x.useMemo)(function(){return t&&t.Consumer&&Object(D.isContextConsumer)(C.a.createElement(t.Consumer,null))?t:E},[t,E]),i=Object(x.useContext)(o),s=Boolean(n.store)&&Boolean(n.store.getState)&&Boolean(n.store.dispatch),l=(Boolean(i)&&Boolean(i.store),(s?n:i).store),u=Object(x.useMemo)(function(){return k(l.dispatch,w)},[l]),e=Object(x.useMemo)(function(){var e,t;return S?(t=(e=T(l,s?null:i.subscription)).notifyNestedSubs.bind(e),[e,t]):j},[l,s,i]),c=e[0],e=e[1],d=Object(x.useMemo)(function(){return s?i:Object(L.a)({},i,{subscription:c})},[s,i,c]),f=Object(x.useReducer)(Y,P,H),p=f[0][0],f=f[1];if(p&&p.error)throw p.error;var h=Object(x.useRef)(),m=Object(x.useRef)(r),g=Object(x.useRef)(),y=Object(x.useRef)(!1),v=M(function(){return g.current&&r===m.current?g.current:u(l.getState(),r)},[l,p,r]),_=(I(A,[m,h,y,r,v,g,e]),I(R,[S,l,c,u,m,h,y,g,e,f],[l,c,u]),Object(x.useMemo)(function(){return C.a.createElement(b,Object(L.a)({},v,{ref:a}))},[a,b,v]));return Object(x.useMemo)(function(){return S?C.a.createElement(o.Provider,{value:d},_):_},[o,_,d])}var a=e?C.a.memo(n):n;return a.WrappedComponent=b,a.displayName=n.displayName=t,l?((e=C.a.forwardRef(function(e,t){return C.a.createElement(a,Object(L.a)({},e,{reactReduxForwardedRef:t}))})).displayName=t,e.WrappedComponent=b,d()(e,b)):d()(a,b)}}function s(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}function m(e,t){if(!s(e,t)){if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),a=Object.keys(t);if(n.length!==a.length)return!1;for(var r=0;re?t.splice(e,t.length-e,n):t.push(n),i({action:"PUSH",location:n,index:e,entries:t}))})},replace:function(e,t){var n=D(e,t,s(),u.location);o.confirmTransitionTo(n,"REPLACE",a,function(e){e&&i({action:"REPLACE",location:u.entries[u.index]=n})})},go:l,goBack:function(){l(-1)},goForward:function(){l(1)},canGo:function(e){return 0<=(e=u.index+e)&&ex',"Tag"),"readonly"!==n&&"interactive"!==n||r.log.warning("Warning: [ shape="+n+" ] is deprecated at [ Tag ]"),"secondary"===a&&r.log.warning("Warning: [ type=secondary ] is deprecated at [ Tag ]"),["count","marked","value","onChange"].forEach(function(e){e in t&&r.log.warning("Warning: [ "+e+" ] is deprecated at [ Tag ]")}),("selected"in t||"defaultSelected"in t)&&r.log.warning("Warning: [ selected|defaultSelected ] is deprecated at [ Tag ], use [ checked|defaultChecked ] at [ Tag.Selectable ] instead of it"),"closed"in t&&r.log.warning("Warning: [ closed ] is deprecated at [ Tag ], use [ onClose ] at [ Tag.Closeable ] instead of it"),"onSelect"in t&&e("onSelect","","Tag"),"afterClose"in t&&r.log.warning("Warning: [ afterClose ] is deprecated at [ Tag ], use [ afterClose ] at [ Tag.Closeable ] instead of it"),t}});o.Group=a.default.config(i.default),o.Selectable=a.default.config(s.default),o.Closable=a.default.config(n.default),o.Closeable=o.Closable,t.default=o,e.exports=t.default},function(e,t,n){"use strict";n(72),n(466)},function(e,t){e=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=e)},function(e,t){e=e.exports={version:"2.6.12"};"number"==typeof __e&&(__e=e)},function(e,t,n){e.exports=!n(113)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,n){"use strict";t.__esModule=!0;var a=o(n(358)),r=o(n(545)),n=o(n(546));function o(e){return e&&e.__esModule?e:{default:e}}a.default.Expand=r.default,a.default.OverlayAnimate=n.default,t.default=a.default,e.exports=t.default},function(e,t,n){"use strict";n(43),n(72),n(114),n(115),n(559)},function(e,t,n){"use strict";t.__esModule=!0;var r=p(n(3)),o=p(n(16)),a=p(n(6)),i=p(n(648)),s=p(n(649)),l=p(n(395)),u=p(n(397)),c=p(n(650)),d=p(n(651)),f=p(n(396)),n=p(n(398));function p(e){return e&&e.__esModule?e:{default:e}}i.default.Header=s.default,i.default.Media=u.default,i.default.Divider=c.default,i.default.Content=d.default,i.default.Actions=n.default,i.default.BulletHeader=l.default,i.default.CollaspeContent=f.default,i.default.CollapseContent=f.default,t.default=a.default.config(i.default,{transform:function(e,t){var n,a;return"titlePrefixLine"in e&&(t("titlePrefixLine","showTitleBullet","Card"),a=(n=e).titlePrefixLine,n=(0,o.default)(n,["titlePrefixLine"]),e=(0,r.default)({showTitleBullet:a},n)),"titleBottomLine"in e&&(t("titleBottomLine","showHeadDivider","Card"),n=(a=e).titleBottomLine,a=(0,o.default)(a,["titleBottomLine"]),e=(0,r.default)({showHeadDivider:n},a)),"bodyHeight"in e&&(t("bodyHeight","contentHeight","Card"),a=(n=e).bodyHeight,t=(0,o.default)(n,["bodyHeight"]),e=(0,r.default)({contentHeight:a},t)),e}}),e.exports=t.default},function(e,t,n){"use strict";n.d(t,"b",function(){return s});var a=n(19),r=n(33),o=n(22),i={namespaces:[]},s=function(e){return function(n){return r.a.get("v3/console/core/namespace/list",{params:e}).then(function(e){var t=e.code,e=e.data;n({type:o.b,data:0===t?e:[]})})}};t.a=function(){var e=0this.menuNode.clientHeight&&(this.menuNode.clientHeight+this.menuNode.scrollTop<(e=this.itemNode.offsetTop+this.itemNode.offsetHeight)?this.menuNode.scrollTop=e-this.menuNode.clientHeight:this.itemNode.offsetTope.length)&&(t=e.length);for(var n=0,a=new Array(t);n>16&255),o.push(r>>8&255),o.push(255&r)),r=r<<6|a.indexOf(t.charAt(i));return 0==(e=n%4*6)?(o.push(r>>16&255),o.push(r>>8&255),o.push(255&r)):18==e?(o.push(r>>10&255),o.push(r>>2&255)):12==e&&o.push(r>>4&255),new Uint8Array(o)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){for(var t,n="",a=0,r=e.length,o=g,i=0;i>18&63]+o[a>>12&63])+o[a>>6&63]+o[63&a]),a=(a<<8)+e[i];return 0==(t=r%3)?n=(n=n+o[a>>18&63]+o[a>>12&63])+o[a>>6&63]+o[63&a]:2==t?n=(n=n+o[a>>10&63]+o[a>>4&63])+o[a<<2&63]+o[64]:1==t&&(n=(n=n+o[a>>2&63]+o[a<<4&63])+o[64]+o[64]),n}}),V=Object.prototype.hasOwnProperty,K=Object.prototype.toString;var s=new a("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null!==e)for(var t,n,a,r=[],o=e,i=0,s=o.length;i>10),56320+(l-65536&1023)),e.position++}else x(e,"unknown escape sequence");n=a=e.position}else w(u)?(T(e,n,a,!0),P(e,D(e,!1,t)),n=a=e.position):e.position===e.lineStart&&N(e)?x(e,"unexpected end of the document within a double quoted scalar"):(e.position++,a=e.position)}x(e,"unexpected end of the stream within a double quoted scalar")}}function ge(e,t){var n,a,r=e.tag,o=e.anchor,i=[],s=!1;if(-1!==e.firstTabInLine)return!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=i),a=e.input.charCodeAt(e.position);0!==a&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,x(e,"tab characters must not be used in indentation")),45===a)&&k(e.input.charCodeAt(e.position+1));)if(s=!0,e.position++,D(e,!0,-1)&&e.lineIndent<=t)i.push(null),a=e.input.charCodeAt(e.position);else if(n=e.line,j(e,t,Z,!1,!0),i.push(e.result),D(e,!0,-1),a=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==a)x(e,"bad indentation of a sequence entry");else if(e.lineIndentt?f=1:e.lineIndent===t?f=0:e.lineIndentt?f=1:e.lineIndent===t?f=0:e.lineIndentt)&&(y&&(i=e.line,s=e.lineStart,l=e.position),j(e,t,_,!0,r)&&(y?m=e.result:g=e.result),y||(L(e,f,p,h,m,g,i,s,l),h=m=g=null),D(e,!0,-1),u=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==u)x(e,"bad indentation of a mapping entry");else if(e.lineIndentl&&(l=e.lineIndent),w(d))u++;else{if(e.lineIndent=t){i=!0,f=e.input.charCodeAt(e.position);continue}e.position=o,e.line=s,e.lineStart=l,e.lineIndent=u;break}}i&&(T(e,r,o,!1),P(e,e.line-s),r=o=e.position,i=!1),M(f)||(o=e.position+1),f=e.input.charCodeAt(++e.position)}if(T(e,r,o,!1),e.result)return 1;e.kind=c,e.result=d}}(e,a,v===n)&&(h=!0,null===e.tag)&&(e.tag="?"):(h=!0,null===e.tag&&null===e.anchor||x(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===f&&(h=s&&ge(e,r))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&x(e,'unacceptable node kind for ! tag; it should be "scalar", not "'+e.kind+'"'),l=0,u=e.implicitTypes.length;l"),null!==e.result&&d.kind!==e.kind&&x(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+d.kind+'", not "'+e.kind+'"'),d.resolve(e.result,e.tag)?(e.result=d.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):x(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||h}function ye(e,t){t=t||{};var n=new de(e=0!==(e=String(e)).length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+="\n"),65279===e.charCodeAt(0))?e.slice(1):e,t),t=e.indexOf("\0");for(-1!==t&&(n.position=t,x(n,"null byte is not allowed in input")),n.input+="\0";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.positiondocument.F=Object<\/script>"),e.close(),u=e.F;t--;)delete u[l][i[t]];return u()};e.exports=Object.create||function(e,t){var n;return null!==e?(a[l]=r(e),n=new a,a[l]=null,n[s]=e):n=u(),void 0===t?n:o(n,t)}},function(e,t,n){var a=n(89).f,r=n(90),o=n(100)("toStringTag");e.exports=function(e,t,n){e&&!r(e=n?e:e.prototype,o)&&a(e,o,{configurable:!0,value:t})}},function(e,t,n){t.f=n(100)},function(e,t,n){var a=n(80),r=n(81),o=n(128),i=n(162),s=n(89).f;e.exports=function(e){var t=r.Symbol||(r.Symbol=!o&&a.Symbol||{});"_"==e.charAt(0)||e in t||s(t,e,{value:i.f(e)})}},function(e,t,n){"use strict";t.__esModule=!0;var a=c(n(219)),r=c(n(520)),o=c(n(521)),i=c(n(522)),s=c(n(523)),l=c(n(524)),u=c(n(525));function c(e){return e&&e.__esModule?e:{default:e}}n(526),a.default.extend(l.default),a.default.extend(s.default),a.default.extend(r.default),a.default.extend(o.default),a.default.extend(i.default),a.default.extend(u.default),a.default.locale("zh-cn");n=a.default;n.isSelf=a.default.isDayjs,a.default.localeData(),t.default=n,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var v=d(n(3)),o=d(n(4)),i=d(n(7)),a=d(n(8)),r=n(0),_=d(r),s=d(n(5)),l=n(31),b=d(n(18)),u=d(n(44)),w=d(n(26)),M=d(n(83)),c=d(n(6)),k=n(11);function d(e){return e&&e.__esModule?e:{default:e}}function f(){}p=r.Component,(0,a.default)(S,p),S.getDerivedStateFromProps=function(e){return"visible"in e?{visible:e.visible}:{}},S.prototype.render=function(){var e,t=this.props,n=t.prefix,a=(t.pure,t.className),r=t.style,o=t.type,i=t.shape,s=t.size,l=t.title,u=t.children,c=(t.defaultVisible,t.visible,t.iconType),d=t.closeable,f=(t.onClose,t.afterClose),p=t.animation,h=t.rtl,t=t.locale,m=(0,v.default)({},k.obj.pickOthers(Object.keys(S.propTypes),this.props)),g=this.state.visible,y=n+"message",o=(0,b.default)(((e={})[y]=!0,e[n+"message-"+o]=o,e[""+n+i]=i,e[""+n+s]=s,e[n+"title-content"]=!!l,e[n+"only-content"]=!l&&!!u,e[a]=a,e)),i=g?_.default.createElement("div",(0,v.default)({role:"alert",style:r},m,{className:o,dir:h?"rtl":void 0}),d?_.default.createElement("a",{role:"button","aria-label":t.closeAriaLabel,className:y+"-close",onClick:this.onClose},_.default.createElement(w.default,{type:"close"})):null,!1!==c?_.default.createElement(w.default,{className:y+"-symbol "+(!c&&y+"-symbol-icon"),type:c}):null,l?_.default.createElement("div",{className:y+"-title"},l):null,u?_.default.createElement("div",{className:y+"-content"},u):null):null;return p?_.default.createElement(M.default.Expand,{animationAppear:!1,afterLeave:f},i):i},r=n=S,n.propTypes={prefix:s.default.string,pure:s.default.bool,className:s.default.string,style:s.default.object,type:s.default.oneOf(["success","warning","error","notice","help","loading"]),shape:s.default.oneOf(["inline","addon","toast"]),size:s.default.oneOf(["medium","large"]),title:s.default.node,children:s.default.node,defaultVisible:s.default.bool,visible:s.default.bool,iconType:s.default.oneOfType([s.default.string,s.default.bool]),closeable:s.default.bool,onClose:s.default.func,afterClose:s.default.func,animation:s.default.bool,locale:s.default.object,rtl:s.default.bool},n.defaultProps={prefix:"next-",pure:!1,type:"success",shape:"inline",size:"medium",defaultVisible:!0,closeable:!1,onClose:f,afterClose:f,animation:!0,locale:u.default.Message};var p,a=r;function S(){var e,t;(0,o.default)(this,S);for(var n=arguments.length,a=Array(n),r=0;r=n.length?(l=!!(d=h(o,u)))&&"get"in d&&!("originalValue"in d.get)?d.get:o[u]:(l=_(o,u),o[u]),l&&!i&&(g[c]=o)}}return o}},function(e,t,n){"use strict";n=n(625);e.exports=Function.prototype.bind||n},function(e,t,n){"use strict";var a=String.prototype.replace,r=/%20/g,o="RFC1738",i="RFC3986";e.exports={default:i,formatters:{RFC1738:function(e){return a.call(e,r,"+")},RFC3986:function(e){return String(e)}},RFC1738:o,RFC3986:i}},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var c=l(n(3)),a=l(n(4)),r=l(n(7)),o=l(n(8)),d=n(0),f=l(d),i=l(n(5)),p=l(n(18)),h=l(n(26)),s=n(11),m=l(n(104));function l(e){return e&&e.__esModule?e:{default:e}}var u,g=s.func.bindCtx,y=s.obj.pickOthers,i=(u=d.Component,(0,o.default)(v,u),v.prototype.getSelected=function(){var e=this.props,t=e._key,n=e.root,e=e.selected,a=n.props.selectMode,n=n.state.selectedKeys;return e||!!a&&-1e.length&&e.every(function(e,t){return e===n[t]})},t.isAvailablePos=function(e,t,n){var n=n[t],a=n.type,n=n.disabled;return r(e,t)&&("item"===a&&!n||"submenu"===a)});t.getFirstAvaliablelChildKey=function(t,n){var e=Object.keys(n).find(function(e){return a(t+"-0",e,n)});return e?n[e].key:null},t.getChildSelected=function(e){var t,n=e.selectMode,a=e.selectedKeys,r=e._k2n,e=e._key;return!!r&&(t=(r[e]&&r[e].pos)+"-",!!n)&&a.some(function(e){return r[e]&&0===r[e].pos.indexOf(t)})}},function(e,t,n){"use strict";n(43),n(72),n(654)},function(e,t,n){"use strict";t.__esModule=!0;var g=d(n(16)),y=d(n(3)),a=d(n(4)),r=d(n(7)),o=d(n(8)),i=n(0),v=d(i),s=d(n(5)),_=d(n(18)),l=d(n(83)),u=d(n(26)),b=n(11),c=d(n(44)),n=d(n(6));function d(e){return e&&e.__esModule?e:{default:e}}var f,p=b.func.noop,h=b.func.bindCtx,m=/blue|green|orange|red|turquoise|yellow/,s=(f=i.Component,(0,o.default)(w,f),w.prototype.componentWillUnmount=function(){this.__destroyed=!0},w.prototype.handleClose=function(e){var t=this,n=this.props,a=n.animation,n=n.onClose,r=b.support.animation&&a;!1===n(e,this.tagNode)||this.__destroyed||this.setState({visible:!1},function(){r||t.props.afterClose(t.tagNode)})},w.prototype.handleBodyClick=function(e){var t=this.props,n=t.closable,a=t.closeArea,t=t.onClick,r=e.currentTarget;if(r&&(r===e.target||r.contains(e.target))&&(n&&"tag"===a&&this.handleClose("tag"),"function"==typeof t))return t(e)},w.prototype.handleTailClick=function(e){e&&e.preventDefault(),e&&e.stopPropagation(),this.handleClose("tail")},w.prototype.handleAnimationInit=function(e){this.props.afterAppear(e)},w.prototype.handleAnimationEnd=function(e){this.props.afterClose(e)},w.prototype.renderAnimatedTag=function(e,t){return v.default.createElement(l.default,{animation:t,afterAppear:this.handleAnimationInit,afterLeave:this.handleAnimationEnd},e)},w.prototype.renderTailNode=function(){var e=this.props,t=e.prefix,n=e.closable,e=e.locale;return n?v.default.createElement("span",{className:t+"tag-close-btn",onClick:this.handleTailClick,role:"button","aria-label":e.delete},v.default.createElement(u.default,{type:"close"})):null},w.prototype.isPresetColor=function(){var e=this.props.color;return!!e&&m.test(e)},w.prototype.getTagStyle=function(){var e=this.props,t=e.color,t=void 0===t?"":t,e=e.style,n=this.isPresetColor();return(0,y.default)({},t&&!n?{backgroundColor:t,borderColor:t,color:"#fff"}:null,e)},w.prototype.render=function(){var t=this,e=this.props,n=e.prefix,a=e.type,r=e.size,o=e.color,i=e._shape,s=e.closable,l=e.closeArea,u=e.className,c=e.children,d=e.animation,f=e.disabled,e=e.rtl,p=this.state.visible,h=this.isPresetColor(),m=b.obj.pickOthers(w.propTypes,this.props),m=(m.style,(0,g.default)(m,["style"])),r=(0,_.default)([n+"tag",n+"tag-"+(s?"closable":i),n+"tag-"+r],((i={})[n+"tag-level-"+a]=!o,i[n+"tag-closable"]=s,i[n+"tag-body-pointer"]=s&&"tag"===l,i[n+"tag-"+o]=o&&h&&"primary"===a,i[n+"tag-"+o+"-inverse"]=o&&h&&"normal"===a,i),u),s=this.renderTailNode(),l=p?v.default.createElement("div",(0,y.default)({className:r,onClick:this.handleBodyClick,onKeyDown:this.onKeyDown,tabIndex:f?"":"0",role:"button","aria-disabled":f,disabled:f,dir:e?"rtl":void 0,ref:function(e){return t.tagNode=e},style:this.getTagStyle()},m),v.default.createElement("span",{className:n+"tag-body"},c),s):null;return d&&b.support.animation?this.renderAnimatedTag(l,n+"tag-zoom"):l},o=i=w,i.propTypes={prefix:s.default.string,type:s.default.oneOf(["normal","primary"]),size:s.default.oneOf(["small","medium","large"]),color:s.default.string,animation:s.default.bool,closeArea:s.default.oneOf(["tag","tail"]),closable:s.default.bool,onClose:s.default.func,afterClose:s.default.func,afterAppear:s.default.func,className:s.default.any,children:s.default.node,onClick:s.default.func,_shape:s.default.oneOf(["default","closable","checkable"]),disabled:s.default.bool,rtl:s.default.bool,locale:s.default.object},i.defaultProps={prefix:"next-",type:"normal",size:"medium",closeArea:"tail",animation:!1,onClose:p,afterClose:p,afterAppear:p,onClick:p,_shape:"default",disabled:!1,rtl:!1,locale:c.default.Tag},o);function w(e){(0,a.default)(this,w);var o=(0,r.default)(this,f.call(this,e));return o.onKeyDown=function(e){var t=o.props,n=t.closable,a=t.closeArea,r=t.onClick,t=t.disabled;e.keyCode!==b.KEYCODE.SPACE||t||(e.preventDefault(),e.stopPropagation(),n?o.handleClose(a):"function"==typeof r&&r(e))},o.state={visible:!0},h(o,["handleBodyClick","handleTailClick","handleAnimationInit","handleAnimationEnd","renderTailNode"]),o}s.displayName="Tag",t.default=n.default.config(s),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var f=r(n(16)),p=r(n(42)),h=r(n(3)),a=(t.isSingle=function(e){return!e||"single"===e},t.isNull=s,t.escapeForReg=o,t.filter=function(e,t){e=o(""+e),e=new RegExp("("+e+")","ig");return e.test(""+t.value)||e.test(""+t.label)},t.loopMap=i,t.parseDataSourceFromChildren=function i(e){var s=1{var t=new TomlError(e.message);return t.code=e.code,t.wrapped=e,t},module.exports.TomlError=TomlError;const createDateTime=__webpack_require__(697),createDateTimeFloat=__webpack_require__(698),createDate=__webpack_require__(699),createTime=__webpack_require__(700),CTRL_I=9,CTRL_J=10,CTRL_M=13,CTRL_CHAR_BOUNDARY=31,CHAR_SP=32,CHAR_QUOT=34,CHAR_NUM=35,CHAR_APOS=39,CHAR_PLUS=43,CHAR_COMMA=44,CHAR_HYPHEN=45,CHAR_PERIOD=46,CHAR_0=48,CHAR_1=49,CHAR_7=55,CHAR_9=57,CHAR_COLON=58,CHAR_EQUALS=61,CHAR_A=65,CHAR_E=69,CHAR_F=70,CHAR_T=84,CHAR_U=85,CHAR_Z=90,CHAR_LOWBAR=95,CHAR_a=97,CHAR_b=98,CHAR_e=101,CHAR_f=102,CHAR_i=105,CHAR_l=108,CHAR_n=110,CHAR_o=111,CHAR_r=114,CHAR_s=115,CHAR_t=116,CHAR_u=117,CHAR_x=120,CHAR_z=122,CHAR_LCUB=123,CHAR_RCUB=125,CHAR_LSQB=91,CHAR_BSOL=92,CHAR_RSQB=93,CHAR_DEL=127,SURROGATE_FIRST=55296,SURROGATE_LAST=57343,escapes={[CHAR_b]:"\b",[CHAR_t]:"\t",[CHAR_n]:"\n",[CHAR_f]:"\f",[CHAR_r]:"\r",[CHAR_QUOT]:'"',[CHAR_BSOL]:"\\"};function isDigit(e){return e>=CHAR_0&&e<=CHAR_9}function isHexit(e){return e>=CHAR_A&&e<=CHAR_F||e>=CHAR_a&&e<=CHAR_f||e>=CHAR_0&&e<=CHAR_9}function isBit(e){return e===CHAR_1||e===CHAR_0}function isOctit(e){return e>=CHAR_0&&e<=CHAR_7}function isAlphaNumQuoteHyphen(e){return e>=CHAR_A&&e<=CHAR_Z||e>=CHAR_a&&e<=CHAR_z||e>=CHAR_0&&e<=CHAR_9||e===CHAR_APOS||e===CHAR_QUOT||e===CHAR_LOWBAR||e===CHAR_HYPHEN}function isAlphaNumHyphen(e){return e>=CHAR_A&&e<=CHAR_Z||e>=CHAR_a&&e<=CHAR_z||e>=CHAR_0&&e<=CHAR_9||e===CHAR_LOWBAR||e===CHAR_HYPHEN}const _type=Symbol("type"),_declared=Symbol("declared"),hasOwnProperty=Object.prototype.hasOwnProperty,defineProperty=Object.defineProperty,descriptor={configurable:!0,enumerable:!0,writable:!0,value:void 0};function hasKey(e,t){if(hasOwnProperty.call(e,t))return 1;"__proto__"===t&&defineProperty(e,"__proto__",descriptor)}const INLINE_TABLE=Symbol("inline-table");function InlineTable(){return Object.defineProperties({},{[_type]:{value:INLINE_TABLE}})}function isInlineTable(e){return null!==e&&"object"==typeof e&&e[_type]===INLINE_TABLE}const TABLE=Symbol("table");function Table(){return Object.defineProperties({},{[_type]:{value:TABLE},[_declared]:{value:!1,writable:!0}})}function isTable(e){return null!==e&&"object"==typeof e&&e[_type]===TABLE}const _contentType=Symbol("content-type"),INLINE_LIST=Symbol("inline-list");function InlineList(e){return Object.defineProperties([],{[_type]:{value:INLINE_LIST},[_contentType]:{value:e}})}function isInlineList(e){return null!==e&&"object"==typeof e&&e[_type]===INLINE_LIST}const LIST=Symbol("list");function List(){return Object.defineProperties([],{[_type]:{value:LIST}})}function isList(e){return null!==e&&"object"==typeof e&&e[_type]===LIST}let _custom;try{const utilInspect=eval("require('util').inspect");_custom=utilInspect.custom}catch(_){}const _inspect=_custom||"inspect";class BoxedBigInt{constructor(e){try{this.value=global.BigInt.asIntN(64,e)}catch(e){this.value=null}Object.defineProperty(this,_type,{value:INTEGER})}isNaN(){return null===this.value}toString(){return String(this.value)}[_inspect](){return`[BigInt: ${this.toString()}]}`}valueOf(){return this.value}}const INTEGER=Symbol("integer");function Integer(e){let t=Number(e);return Object.is(t,-0)&&(t=0),global.BigInt&&!Number.isSafeInteger(t)?new BoxedBigInt(e):Object.defineProperties(new Number(t),{isNaN:{value:function(){return isNaN(this)}},[_type]:{value:INTEGER},[_inspect]:{value:()=>`[Integer: ${e}]`}})}function isInteger(e){return null!==e&&"object"==typeof e&&e[_type]===INTEGER}const FLOAT=Symbol("float");function Float(e){return Object.defineProperties(new Number(e),{[_type]:{value:FLOAT},[_inspect]:{value:()=>`[Float: ${e}]`}})}function isFloat(e){return null!==e&&"object"==typeof e&&e[_type]===FLOAT}function tomlType(e){var t=typeof e;if("object"==t){if(null===e)return"null";if(e instanceof Date)return"datetime";if(_type in e)switch(e[_type]){case INLINE_TABLE:return"inline-table";case INLINE_LIST:return"inline-list";case TABLE:return"table";case LIST:return"list";case FLOAT:return"float";case INTEGER:return"integer"}}return t}function makeParserClass(e){class t extends e{constructor(){super(),this.ctx=this.obj=Table()}atEndOfWord(){return this.char===CHAR_NUM||this.char===CTRL_I||this.char===CHAR_SP||this.atEndOfLine()}atEndOfLine(){return this.char===e.END||this.char===CTRL_J||this.char===CTRL_M}parseStart(){if(this.char===e.END)return null;if(this.char===CHAR_LSQB)return this.call(this.parseTableOrList);if(this.char===CHAR_NUM)return this.call(this.parseComment);if(this.char===CTRL_J||this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M)return null;if(isAlphaNumQuoteHyphen(this.char))return this.callNow(this.parseAssignStatement);throw this.error(new TomlError(`Unknown character "${this.char}"`))}parseWhitespaceToEOL(){if(this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M)return null;if(this.char===CHAR_NUM)return this.goto(this.parseComment);if(this.char===e.END||this.char===CTRL_J)return this.return();throw this.error(new TomlError("Unexpected character, expected only whitespace or comments till end of line"))}parseAssignStatement(){return this.callNow(this.parseAssign,this.recordAssignStatement)}recordAssignStatement(e){let t=this.ctx;var n,a=e.key.pop();for(n of e.key){if(hasKey(t,n)&&!isTable(t[n]))throw this.error(new TomlError("Can't redefine existing key"));t=t[n]=t[n]||Table()}if(hasKey(t,a))throw this.error(new TomlError("Can't redefine existing key"));return t[_declared]=!0,isInteger(e.value)||isFloat(e.value)?t[a]=e.value.valueOf():t[a]=e.value,this.goto(this.parseWhitespaceToEOL)}parseAssign(){return this.callNow(this.parseKeyword,this.recordAssignKeyword)}recordAssignKeyword(e){return this.state.resultTable?this.state.resultTable.push(e):this.state.resultTable=[e],this.goto(this.parseAssignKeywordPreDot)}parseAssignKeywordPreDot(){return this.char===CHAR_PERIOD?this.next(this.parseAssignKeywordPostDot):this.char!==CHAR_SP&&this.char!==CTRL_I?this.goto(this.parseAssignEqual):void 0}parseAssignKeywordPostDot(){if(this.char!==CHAR_SP&&this.char!==CTRL_I)return this.callNow(this.parseKeyword,this.recordAssignKeyword)}parseAssignEqual(){if(this.char===CHAR_EQUALS)return this.next(this.parseAssignPreValue);throw this.error(new TomlError('Invalid character, expected "="'))}parseAssignPreValue(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseValue,this.recordAssignValue)}recordAssignValue(e){return this.returnNow({key:this.state.resultTable,value:e})}parseComment(){do{if(this.char===e.END||this.char===CTRL_J)return this.return();if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("comments")}while(this.nextChar())}parseTableOrList(){if(this.char!==CHAR_LSQB)return this.goto(this.parseTable);this.next(this.parseList)}parseTable(){return this.ctx=this.obj,this.goto(this.parseTableNext)}parseTableNext(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseKeyword,this.parseTableMore)}parseTableMore(e){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CHAR_RSQB){if(!hasKey(this.ctx,e)||isTable(this.ctx[e])&&!this.ctx[e][_declared])return this.ctx=this.ctx[e]=this.ctx[e]||Table(),this.ctx[_declared]=!0,this.next(this.parseWhitespaceToEOL);throw this.error(new TomlError("Can't redefine existing key"))}if(this.char!==CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));if(hasKey(this.ctx,e))if(isTable(this.ctx[e]))this.ctx=this.ctx[e];else{if(!isList(this.ctx[e]))throw this.error(new TomlError("Can't redefine existing key"));this.ctx=this.ctx[e][this.ctx[e].length-1]}else this.ctx=this.ctx[e]=Table();return this.next(this.parseTableNext)}parseList(){return this.ctx=this.obj,this.goto(this.parseListNext)}parseListNext(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseKeyword,this.parseListMore)}parseListMore(e){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CHAR_RSQB){if(hasKey(this.ctx,e)||(this.ctx[e]=List()),isInlineList(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline array"));var t;if(isList(this.ctx[e]))return t=Table(),this.ctx[e].push(t),this.ctx=t,this.next(this.parseListEnd);throw this.error(new TomlError("Can't redefine an existing key"))}if(this.char!==CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));if(hasKey(this.ctx,e)){if(isInlineList(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline array"));if(isInlineTable(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline table"));if(isList(this.ctx[e]))this.ctx=this.ctx[e][this.ctx[e].length-1];else{if(!isTable(this.ctx[e]))throw this.error(new TomlError("Can't redefine an existing key"));this.ctx=this.ctx[e]}}else this.ctx=this.ctx[e]=Table();return this.next(this.parseListNext)}parseListEnd(e){if(this.char===CHAR_RSQB)return this.next(this.parseWhitespaceToEOL);throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"))}parseValue(){if(this.char===e.END)throw this.error(new TomlError("Key without value"));if(this.char===CHAR_QUOT)return this.next(this.parseDoubleString);if(this.char===CHAR_APOS)return this.next(this.parseSingleString);if(this.char===CHAR_HYPHEN||this.char===CHAR_PLUS)return this.goto(this.parseNumberSign);if(this.char===CHAR_i)return this.next(this.parseInf);if(this.char===CHAR_n)return this.next(this.parseNan);if(isDigit(this.char))return this.goto(this.parseNumberOrDateTime);if(this.char===CHAR_t||this.char===CHAR_f)return this.goto(this.parseBoolean);if(this.char===CHAR_LSQB)return this.call(this.parseInlineList,this.recordValue);if(this.char===CHAR_LCUB)return this.call(this.parseInlineTable,this.recordValue);throw this.error(new TomlError("Unexpected character, expecting string, number, datetime, boolean, inline array or inline table"))}recordValue(e){return this.returnNow(e)}parseInf(){if(this.char===CHAR_n)return this.next(this.parseInf2);throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'))}parseInf2(){if(this.char===CHAR_f)return"-"===this.state.buf?this.return(-1/0):this.return(1/0);throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'))}parseNan(){if(this.char===CHAR_a)return this.next(this.parseNan2);throw this.error(new TomlError('Unexpected character, expected "nan"'))}parseNan2(){if(this.char===CHAR_n)return this.return(NaN);throw this.error(new TomlError('Unexpected character, expected "nan"'))}parseKeyword(){return this.char===CHAR_QUOT?this.next(this.parseBasicString):this.char===CHAR_APOS?this.next(this.parseLiteralString):this.goto(this.parseBareKey)}parseBareKey(){do{if(this.char===e.END)throw this.error(new TomlError("Key ended without value"));if(!isAlphaNumHyphen(this.char)){if(0===this.state.buf.length)throw this.error(new TomlError("Empty bare keys are not allowed"));return this.returnNow()}}while(this.consume(),this.nextChar())}parseSingleString(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiStringMaybe):this.goto(this.parseLiteralString)}parseLiteralString(){do{if(this.char===CHAR_APOS)return this.return();if(this.atEndOfLine())throw this.error(new TomlError("Unterminated string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}parseLiteralMultiStringMaybe(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiString):this.returnNow()}parseLiteralMultiString(){return this.char===CTRL_M?null:this.char===CTRL_J?this.next(this.parseLiteralMultiStringContent):this.goto(this.parseLiteralMultiStringContent)}parseLiteralMultiStringContent(){do{if(this.char===CHAR_APOS)return this.next(this.parseLiteralMultiEnd);if(this.char===e.END)throw this.error(new TomlError("Unterminated multi-line string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I&&this.char!==CTRL_J&&this.char!==CTRL_M)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}parseLiteralMultiEnd(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiEnd2):(this.state.buf+="'",this.goto(this.parseLiteralMultiStringContent))}parseLiteralMultiEnd2(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiEnd3):(this.state.buf+="''",this.goto(this.parseLiteralMultiStringContent))}parseLiteralMultiEnd3(){return this.char===CHAR_APOS?(this.state.buf+="'",this.next(this.parseLiteralMultiEnd4)):this.returnNow()}parseLiteralMultiEnd4(){return this.char===CHAR_APOS?(this.state.buf+="'",this.return()):this.returnNow()}parseDoubleString(){return this.char===CHAR_QUOT?this.next(this.parseMultiStringMaybe):this.goto(this.parseBasicString)}parseBasicString(){do{if(this.char===CHAR_BSOL)return this.call(this.parseEscape,this.recordEscapeReplacement);if(this.char===CHAR_QUOT)return this.return();if(this.atEndOfLine())throw this.error(new TomlError("Unterminated string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}recordEscapeReplacement(e){return this.state.buf+=e,this.goto(this.parseBasicString)}parseMultiStringMaybe(){return this.char===CHAR_QUOT?this.next(this.parseMultiString):this.returnNow()}parseMultiString(){return this.char===CTRL_M?null:this.char===CTRL_J?this.next(this.parseMultiStringContent):this.goto(this.parseMultiStringContent)}parseMultiStringContent(){do{if(this.char===CHAR_BSOL)return this.call(this.parseMultiEscape,this.recordMultiEscapeReplacement);if(this.char===CHAR_QUOT)return this.next(this.parseMultiEnd);if(this.char===e.END)throw this.error(new TomlError("Unterminated multi-line string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I&&this.char!==CTRL_J&&this.char!==CTRL_M)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}errorControlCharIn(e){let t="\\u00";return this.char<16&&(t+="0"),t+=this.char.toString(16),this.error(new TomlError(`Control characters (codes < 0x1f and 0x7f) are not allowed in ${e}, use ${t} instead`))}recordMultiEscapeReplacement(e){return this.state.buf+=e,this.goto(this.parseMultiStringContent)}parseMultiEnd(){return this.char===CHAR_QUOT?this.next(this.parseMultiEnd2):(this.state.buf+='"',this.goto(this.parseMultiStringContent))}parseMultiEnd2(){return this.char===CHAR_QUOT?this.next(this.parseMultiEnd3):(this.state.buf+='""',this.goto(this.parseMultiStringContent))}parseMultiEnd3(){return this.char===CHAR_QUOT?(this.state.buf+='"',this.next(this.parseMultiEnd4)):this.returnNow()}parseMultiEnd4(){return this.char===CHAR_QUOT?(this.state.buf+='"',this.return()):this.returnNow()}parseMultiEscape(){return this.char===CTRL_M||this.char===CTRL_J?this.next(this.parseMultiTrim):this.char===CHAR_SP||this.char===CTRL_I?this.next(this.parsePreMultiTrim):this.goto(this.parseEscape)}parsePreMultiTrim(){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CTRL_M||this.char===CTRL_J)return this.next(this.parseMultiTrim);throw this.error(new TomlError("Can't escape whitespace"))}parseMultiTrim(){return this.char===CTRL_J||this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M?null:this.returnNow()}parseEscape(){if(this.char in escapes)return this.return(escapes[this.char]);if(this.char===CHAR_u)return this.call(this.parseSmallUnicode,this.parseUnicodeReturn);if(this.char===CHAR_U)return this.call(this.parseLargeUnicode,this.parseUnicodeReturn);throw this.error(new TomlError("Unknown escape character: "+this.char))}parseUnicodeReturn(e){try{var t=parseInt(e,16);if(t>=SURROGATE_FIRST&&t<=SURROGATE_LAST)throw this.error(new TomlError("Invalid unicode, character in range 0xD800 - 0xDFFF is reserved"));return this.returnNow(String.fromCodePoint(t))}catch(e){throw this.error(TomlError.wrap(e))}}parseSmallUnicode(){if(!isHexit(this.char))throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"));if(this.consume(),4<=this.state.buf.length)return this.return()}parseLargeUnicode(){if(!isHexit(this.char))throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"));if(this.consume(),8<=this.state.buf.length)return this.return()}parseNumberSign(){return this.consume(),this.next(this.parseMaybeSignedInfOrNan)}parseMaybeSignedInfOrNan(){return this.char===CHAR_i?this.next(this.parseInf):this.char===CHAR_n?this.next(this.parseNan):this.callNow(this.parseNoUnder,this.parseNumberIntegerStart)}parseNumberIntegerStart(){return this.char===CHAR_0?(this.consume(),this.next(this.parseNumberIntegerExponentOrDecimal)):this.goto(this.parseNumberInteger)}parseNumberIntegerExponentOrDecimal(){return this.char===CHAR_PERIOD?(this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat)):this.char===CHAR_E||this.char===CHAR_e?(this.consume(),this.next(this.parseNumberExponentSign)):this.returnNow(Integer(this.state.buf))}parseNumberInteger(){if(!isDigit(this.char)){if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnder);if(this.char===CHAR_E||this.char===CHAR_e)return this.consume(),this.next(this.parseNumberExponentSign);if(this.char===CHAR_PERIOD)return this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat);var e=Integer(this.state.buf);if(e.isNaN())throw this.error(new TomlError("Invalid number"));return this.returnNow(e)}this.consume()}parseNoUnder(){if(this.char===CHAR_LOWBAR||this.char===CHAR_PERIOD||this.char===CHAR_E||this.char===CHAR_e)throw this.error(new TomlError("Unexpected character, expected digit"));if(this.atEndOfWord())throw this.error(new TomlError("Incomplete number"));return this.returnNow()}parseNoUnderHexOctBinLiteral(){if(this.char===CHAR_LOWBAR||this.char===CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected digit"));if(this.atEndOfWord())throw this.error(new TomlError("Incomplete number"));return this.returnNow()}parseNumberFloat(){return this.char===CHAR_LOWBAR?this.call(this.parseNoUnder,this.parseNumberFloat):isDigit(this.char)?void this.consume():this.char===CHAR_E||this.char===CHAR_e?(this.consume(),this.next(this.parseNumberExponentSign)):this.returnNow(Float(this.state.buf))}parseNumberExponentSign(){if(isDigit(this.char))return this.goto(this.parseNumberExponent);if(this.char!==CHAR_HYPHEN&&this.char!==CHAR_PLUS)throw this.error(new TomlError("Unexpected character, expected -, + or digit"));this.consume(),this.call(this.parseNoUnder,this.parseNumberExponent)}parseNumberExponent(){if(!isDigit(this.char))return this.char===CHAR_LOWBAR?this.call(this.parseNoUnder):this.returnNow(Float(this.state.buf));this.consume()}parseNumberOrDateTime(){return this.char===CHAR_0?(this.consume(),this.next(this.parseNumberBaseOrDateTime)):this.goto(this.parseNumberOrDateTimeOnly)}parseNumberOrDateTimeOnly(){return this.char===CHAR_LOWBAR?this.call(this.parseNoUnder,this.parseNumberInteger):isDigit(this.char)?(this.consume(),void(4{for(t=String(t);t.length "+o[t]+"\n")+(n+" ");for(let e=0;er&&!o.warned&&(o.warned=!0,(a=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit")).name="MaxListenersExceededWarning",a.emitter=e,a.type=t,a.count=o.length,n=a,console)&&console.warn&&console.warn(n)),e}function f(e,t,n){e={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},t=function(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}.bind(e);return t.listener=n,e.wrapFn=t}function p(e,t,n){e=e._events;if(void 0===e)return[];e=e[t];if(void 0===e)return[];if("function"==typeof e)return n?[e.listener||e]:[e];if(n){for(var a=e,r=new Array(a.length),o=0;o=u,u=(0,D.default)(((u={})[n+"upload-inner"]=!0,u[n+"hidden"]=x,u)),C=this.props.children;return"card"===r&&(r=(0,D.default)(((r={})[n+"upload-card"]=!0,r[n+"disabled"]=l,r)),C=O.default.createElement("div",{className:r},O.default.createElement(P.default,{size:"large",type:"add",className:n+"upload-add-icon"}),O.default.createElement("div",{tabIndex:"0",role:"button",className:n+"upload-text"},C))),b?"function"==typeof w?(b=(0,D.default)(((r={})[n+"form-preview"]=!0,r[o]=!!o,r)),O.default.createElement("div",{style:i,className:b},w(this.state.value,this.props))):t?O.default.createElement(Y.default,{isPreview:!0,listType:t,style:i,className:o,value:this.state.value,onPreview:m}):null:(n=l?N.func.prevent:p,r=N.obj.pickAttrsWith(this.props,"data-"),O.default.createElement("div",(0,T.default)({className:f,style:i},r),O.default.createElement(j.default,(0,T.default)({},e,{name:M,beforeUpload:d,dragable:a,disabled:l||x,className:u,onSelect:this.onSelect,onDrop:this.onDrop,onProgress:this.onProgress,onSuccess:this.onSuccess,onError:this.onError,ref:this.saveUploaderRef}),C),t||g?O.default.createElement(Y.default,{useDataURL:s,fileNameRender:k,actionRender:S,uploader:this,listType:t,value:this.state.value,closable:c,onRemove:n,progressProps:v,onCancel:h,onPreview:m,extraRender:y,rtl:_,previewOnFileName:E}):null))},i=u=h,u.displayName="Upload",u.propTypes=(0,T.default)({},c.default.propTypes,Y.default.propTypes,{prefix:s.default.string.isRequired,action:s.default.string,value:s.default.array,defaultValue:s.default.array,shape:s.default.oneOf(["card"]),listType:s.default.oneOf(["text","image","card"]),list:s.default.any,name:s.default.string,data:s.default.oneOfType([s.default.object,s.default.func]),formatter:s.default.func,limit:s.default.number,timeout:s.default.number,dragable:s.default.bool,closable:s.default.bool,useDataURL:s.default.bool,disabled:s.default.bool,onSelect:s.default.func,onProgress:s.default.func,onChange:s.default.func,onSuccess:s.default.func,afterSelect:s.default.func,onRemove:s.default.func,onError:s.default.func,beforeUpload:s.default.func,onDrop:s.default.func,className:s.default.string,style:s.default.object,children:s.default.node,autoUpload:s.default.bool,request:s.default.func,progressProps:s.default.object,rtl:s.default.bool,isPreview:s.default.bool,renderPreview:s.default.func,fileKeyName:s.default.string,fileNameRender:s.default.func,actionRender:s.default.func,previewOnFileName:s.default.bool}),u.defaultProps=(0,T.default)({},c.default.defaultProps,{prefix:"next-",limit:1/0,autoUpload:!0,closable:!0,onSelect:n,onProgress:n,onChange:n,onSuccess:n,onRemove:n,onError:n,onDrop:n,beforeUpload:n,afterSelect:n,previewOnFileName:!1}),a=function(){var u=this;this.onSelect=function(e){var t,n,a=u.props,r=a.autoUpload,o=a.afterSelect,i=a.onSelect,a=a.limit,s=u.state.value.length+e.length,l=a-u.state.value.length;l<=0||(t=e=e.map(function(e){e=(0,d.fileToObject)(e);return e.state="selected",e}),n=[],ai||s+a.width>o):t<0||e<0||t+a.height>u.height||e+a.width>u.width}function L(e,t,n,a){var r=a.overlayInfo,a=a.containerInfo,n=n.split("");return 1===n.length&&n.push(""),t<0&&(n=[n[0].replace("t","b"),n[1].replace("b","t")]),e<0&&(n=[n[0].replace("l","r"),n[1].replace("r","l")]),t+r.height>a.height&&(n=[n[0].replace("b","t"),n[1].replace("t","b")]),(n=e+r.width>a.width?[n[0].replace("r","l"),n[1].replace("l","r")]:n).join("")}function O(e,t,n){var a=n.overlayInfo,n=n.containerInfo;return(t=t<0?0:t)+a.height>n.height&&(t=n.height-a.height),{left:e=(e=e<0?0:e)+a.width>n.width?n.width-a.width:e,top:t}}function be(e){var r,o,i,s,t,n,a,l,u,c,d,f=e.target,p=e.overlay,h=e.container,m=e.scrollNode,g=e.placement,y=e.placementOffset,y=void 0===y?0:y,v=e.points,v=void 0===v?["tl","bl"]:v,_=e.offset,_=void 0===_?[0,0]:_,b=e.position,b=void 0===b?"absolute":b,w=e.beforePosition,M=e.autoAdjust,M=void 0===M||M,k=e.autoHideScrollOverflow,k=void 0===k||k,e=e.rtl,S="offsetWidth"in(S=p)&&"offsetHeight"in S?{width:S.offsetWidth,height:S.offsetHeight}:{width:(S=S.getBoundingClientRect()).width,height:S.height},E=S.width,S=S.height;return"fixed"===b?(l={config:{placement:void 0,points:void 0},style:{position:b,left:_[0],top:_[1]}},w?w(l,{overlay:{node:p,width:E,height:S}}):l):(l=f.getBoundingClientRect(),r=l.width,o=l.height,i=l.left,s=l.top,t=(l=x(h)).left,l=l.top,u=h.scrollWidth,c=h.scrollHeight,n=h.scrollTop,a=h.scrollLeft,u=(l=C(g,t={targetInfo:{width:r,height:o,left:i,top:s},containerInfo:{left:t,top:l,width:u,height:c,scrollTop:n,scrollLeft:a},overlayInfo:{width:E,height:S},points:v,placementOffset:y,offset:_,container:h,rtl:e})).left,c=l.top,n=l.points,a=function(e){for(var t=e;t;){var n=he(t,"overflow");if(null!=n&&n.match(/auto|scroll|hidden/))return t;t=t.parentNode}return document.documentElement}(h),M&&g&&T(u,c,a,t)&&(g!==(v=L(u,c,g,t))&&(c=T(_=(y=C(v,t)).left,e=y.top,a,t)&&v!==(l=L(_,e,v,t))?(u=(M=O((h=C(g=l,t)).left,h.top,t)).left,M.top):(g=v,u=_,e)),u=(y=O(u,c,t)).left,c=y.top),d={config:{placement:g,points:n},style:{position:b,left:Math.round(u),top:Math.round(c)}},k&&g&&null!=m&&m.length&&m.forEach(function(e){var e=e.getBoundingClientRect(),t=e.top,n=e.left,a=e.width,e=e.height;d.style.display=s+o=e.length?{done:!0}:{done:!1,value:e[n++]}};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=new Array(t);nn.clientHeight&&0 16.8.0")},p.prototype.validate=function(e,t){this.validateCallback(e,t)},p.prototype.reset=function(e){var t=1","Select");t=l(e,t);return e.onInputUpdate&&(t.onSearch=e.onInputUpdate,t.showSearch=!0),t}}),t.default=a.default.config(r.default,{transform:l,exportNames:["focusInput","handleSearchClear"]}),e.exports=t.default},function(M,e,t){"use strict";t.d(e,"a",function(){return a}),t.d(e,"b",function(){return U});var x=t(0),C=t.n(x),c=C.a.createContext(null);function l(){return n}var n=function(e){e()};var r={notify:function(){},get:function(){return[]}};function T(t,n){var o,i=r;function s(){e.onStateChange&&e.onStateChange()}function a(){var e,a,r;o||(o=n?n.addNestedSub(s):t.subscribe(s),e=l(),r=a=null,i={clear:function(){r=a=null},notify:function(){e(function(){for(var e=a;e;)e.callback(),e=e.next})},get:function(){for(var e=[],t=a;t;)e.push(t),t=t.next;return e},subscribe:function(e){var t=!0,n=r={callback:e,next:null,prev:r};return n.prev?n.prev.next=n:a=n,function(){t&&null!==a&&(t=!1,n.next?n.next.prev=n.prev:r=n.prev,n.prev?n.prev.next=n.next:a=n.next)}}})}var e={addNestedSub:function(e){return a(),i.subscribe(e)},notifyNestedSubs:function(){i.notify()},handleChangeWrapper:s,isSubscribed:function(){return Boolean(o)},trySubscribe:a,tryUnsubscribe:function(){o&&(o(),o=void 0,i.clear(),i=r)},getListeners:function(){return i}};return e}var o="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?x.useLayoutEffect:x.useEffect;var a=function(e){var t=e.store,n=e.context,e=e.children,a=Object(x.useMemo)(function(){var e=T(t);return{store:t,subscription:e}},[t]),r=Object(x.useMemo)(function(){return t.getState()},[t]),n=(o(function(){var e=a.subscription;return e.onStateChange=e.notifyNestedSubs,e.trySubscribe(),r!==t.getState()&&e.notifyNestedSubs(),function(){e.tryUnsubscribe(),e.onStateChange=null}},[a,r]),n||c);return C.a.createElement(n.Provider,{value:a},e)},L=t(41),O=t(56),e=t(107),d=t.n(e),D=t(430),f=["getDisplayName","methodName","renderCountProp","shouldHandleStateChanges","storeKey","withRef","forwardRef","context"],N=["reactReduxForwardedRef"],P=[],j=[null,null];function Y(e,t){e=e[1];return[t.payload,e+1]}function I(e,t,n){o(function(){return e.apply(void 0,t)},n)}function A(e,t,n,a,r,o,i){e.current=a,t.current=r,n.current=!1,o.current&&(o.current=null,i())}function R(e,a,t,r,o,i,s,l,u,c){var d,f;if(e)return d=!1,f=null,t.onStateChange=e=function(){if(!d){var e,t,n=a.getState();try{e=r(n,o.current)}catch(e){f=t=e}t||(f=null),e===i.current?s.current||u():(i.current=e,l.current=e,s.current=!0,c({type:"STORE_UPDATED",payload:{error:t}}))}},t.trySubscribe(),e(),function(){if(d=!0,t.tryUnsubscribe(),t.onStateChange=null,f)throw f}}var H=function(){return[null,0]};function i(k,e){var e=e=void 0===e?{}:e,t=e.getDisplayName,r=void 0===t?function(e){return"ConnectAdvanced("+e+")"}:t,t=e.methodName,o=void 0===t?"connectAdvanced":t,t=e.renderCountProp,i=void 0===t?void 0:t,t=e.shouldHandleStateChanges,S=void 0===t||t,t=e.storeKey,s=void 0===t?"store":t,t=(e.withRef,e.forwardRef),l=void 0!==t&&t,t=e.context,t=void 0===t?c:t,u=Object(O.a)(e,f),E=t;return function(b){var e=b.displayName||b.name||"Component",t=r(e),w=Object(L.a)({},u,{getDisplayName:r,methodName:o,renderCountProp:i,shouldHandleStateChanges:S,storeKey:s,displayName:t,wrappedComponentName:e,WrappedComponent:b}),e=u.pure;var M=e?x.useMemo:function(e){return e()};function n(n){var e=Object(x.useMemo)(function(){var e=n.reactReduxForwardedRef,t=Object(O.a)(n,N);return[n.context,e,t]},[n]),t=e[0],a=e[1],r=e[2],o=Object(x.useMemo)(function(){return t&&t.Consumer&&Object(D.isContextConsumer)(C.a.createElement(t.Consumer,null))?t:E},[t,E]),i=Object(x.useContext)(o),s=Boolean(n.store)&&Boolean(n.store.getState)&&Boolean(n.store.dispatch),l=(Boolean(i)&&Boolean(i.store),(s?n:i).store),u=Object(x.useMemo)(function(){return k(l.dispatch,w)},[l]),e=Object(x.useMemo)(function(){var e,t;return S?(t=(e=T(l,s?null:i.subscription)).notifyNestedSubs.bind(e),[e,t]):j},[l,s,i]),c=e[0],e=e[1],d=Object(x.useMemo)(function(){return s?i:Object(L.a)({},i,{subscription:c})},[s,i,c]),f=Object(x.useReducer)(Y,P,H),p=f[0][0],f=f[1];if(p&&p.error)throw p.error;var h=Object(x.useRef)(),m=Object(x.useRef)(r),g=Object(x.useRef)(),y=Object(x.useRef)(!1),v=M(function(){return g.current&&r===m.current?g.current:u(l.getState(),r)},[l,p,r]),_=(I(A,[m,h,y,r,v,g,e]),I(R,[S,l,c,u,m,h,y,g,e,f],[l,c,u]),Object(x.useMemo)(function(){return C.a.createElement(b,Object(L.a)({},v,{ref:a}))},[a,b,v]));return Object(x.useMemo)(function(){return S?C.a.createElement(o.Provider,{value:d},_):_},[o,_,d])}var a=e?C.a.memo(n):n;return a.WrappedComponent=b,a.displayName=n.displayName=t,l?((e=C.a.forwardRef(function(e,t){return C.a.createElement(a,Object(L.a)({},e,{reactReduxForwardedRef:t}))})).displayName=t,e.WrappedComponent=b,d()(e,b)):d()(a,b)}}function s(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}function m(e,t){if(!s(e,t)){if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),a=Object.keys(t);if(n.length!==a.length)return!1;for(var r=0;re?t.splice(e,t.length-e,n):t.push(n),i({action:"PUSH",location:n,index:e,entries:t}))})},replace:function(e,t){var n=D(e,t,s(),u.location);o.confirmTransitionTo(n,"REPLACE",a,function(e){e&&i({action:"REPLACE",location:u.entries[u.index]=n})})},go:l,goBack:function(){l(-1)},goForward:function(){l(1)},canGo:function(e){return 0<=(e=u.index+e)&&ex',"Tag"),"readonly"!==n&&"interactive"!==n||r.log.warning("Warning: [ shape="+n+" ] is deprecated at [ Tag ]"),"secondary"===a&&r.log.warning("Warning: [ type=secondary ] is deprecated at [ Tag ]"),["count","marked","value","onChange"].forEach(function(e){e in t&&r.log.warning("Warning: [ "+e+" ] is deprecated at [ Tag ]")}),("selected"in t||"defaultSelected"in t)&&r.log.warning("Warning: [ selected|defaultSelected ] is deprecated at [ Tag ], use [ checked|defaultChecked ] at [ Tag.Selectable ] instead of it"),"closed"in t&&r.log.warning("Warning: [ closed ] is deprecated at [ Tag ], use [ onClose ] at [ Tag.Closeable ] instead of it"),"onSelect"in t&&e("onSelect","","Tag"),"afterClose"in t&&r.log.warning("Warning: [ afterClose ] is deprecated at [ Tag ], use [ afterClose ] at [ Tag.Closeable ] instead of it"),t}});o.Group=a.default.config(i.default),o.Selectable=a.default.config(s.default),o.Closable=a.default.config(n.default),o.Closeable=o.Closable,t.default=o,e.exports=t.default},function(e,t,n){"use strict";n(72),n(466)},function(e,t){e=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=e)},function(e,t){e=e.exports={version:"2.6.12"};"number"==typeof __e&&(__e=e)},function(e,t,n){e.exports=!n(113)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t,n){"use strict";t.__esModule=!0;var a=o(n(358)),r=o(n(545)),n=o(n(546));function o(e){return e&&e.__esModule?e:{default:e}}a.default.Expand=r.default,a.default.OverlayAnimate=n.default,t.default=a.default,e.exports=t.default},function(e,t,n){"use strict";n(43),n(72),n(114),n(115),n(559)},function(e,t,n){"use strict";t.__esModule=!0;var r=p(n(3)),o=p(n(17)),a=p(n(6)),i=p(n(648)),s=p(n(649)),l=p(n(395)),u=p(n(397)),c=p(n(650)),d=p(n(651)),f=p(n(396)),n=p(n(398));function p(e){return e&&e.__esModule?e:{default:e}}i.default.Header=s.default,i.default.Media=u.default,i.default.Divider=c.default,i.default.Content=d.default,i.default.Actions=n.default,i.default.BulletHeader=l.default,i.default.CollaspeContent=f.default,i.default.CollapseContent=f.default,t.default=a.default.config(i.default,{transform:function(e,t){var n,a;return"titlePrefixLine"in e&&(t("titlePrefixLine","showTitleBullet","Card"),a=(n=e).titlePrefixLine,n=(0,o.default)(n,["titlePrefixLine"]),e=(0,r.default)({showTitleBullet:a},n)),"titleBottomLine"in e&&(t("titleBottomLine","showHeadDivider","Card"),n=(a=e).titleBottomLine,a=(0,o.default)(a,["titleBottomLine"]),e=(0,r.default)({showHeadDivider:n},a)),"bodyHeight"in e&&(t("bodyHeight","contentHeight","Card"),a=(n=e).bodyHeight,t=(0,o.default)(n,["bodyHeight"]),e=(0,r.default)({contentHeight:a},t)),e}}),e.exports=t.default},function(e,t,n){"use strict";n.d(t,"b",function(){return s});var a=n(12),r=n(33),o=n(22),i={namespaces:[]},s=function(e){return function(n){return r.a.get("v3/console/core/namespace/list",{params:e}).then(function(e){var t=e.code,e=e.data;n({type:o.b,data:0===t?e:[]})})}};t.a=function(){var e=0this.menuNode.clientHeight&&(this.menuNode.clientHeight+this.menuNode.scrollTop<(e=this.itemNode.offsetTop+this.itemNode.offsetHeight)?this.menuNode.scrollTop=e-this.menuNode.clientHeight:this.itemNode.offsetTope.length)&&(t=e.length);for(var n=0,a=new Array(t);n>16&255),o.push(r>>8&255),o.push(255&r)),r=r<<6|a.indexOf(t.charAt(i));return 0==(e=n%4*6)?(o.push(r>>16&255),o.push(r>>8&255),o.push(255&r)):18==e?(o.push(r>>10&255),o.push(r>>2&255)):12==e&&o.push(r>>4&255),new Uint8Array(o)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){for(var t,n="",a=0,r=e.length,o=g,i=0;i>18&63]+o[a>>12&63])+o[a>>6&63]+o[63&a]),a=(a<<8)+e[i];return 0==(t=r%3)?n=(n=n+o[a>>18&63]+o[a>>12&63])+o[a>>6&63]+o[63&a]:2==t?n=(n=n+o[a>>10&63]+o[a>>4&63])+o[a<<2&63]+o[64]:1==t&&(n=(n=n+o[a>>2&63]+o[a<<4&63])+o[64]+o[64]),n}}),V=Object.prototype.hasOwnProperty,K=Object.prototype.toString;var s=new a("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null!==e)for(var t,n,a,r=[],o=e,i=0,s=o.length;i>10),56320+(l-65536&1023)),e.position++}else x(e,"unknown escape sequence");n=a=e.position}else w(u)?(T(e,n,a,!0),P(e,D(e,!1,t)),n=a=e.position):e.position===e.lineStart&&N(e)?x(e,"unexpected end of the document within a double quoted scalar"):(e.position++,a=e.position)}x(e,"unexpected end of the stream within a double quoted scalar")}}function ge(e,t){var n,a,r=e.tag,o=e.anchor,i=[],s=!1;if(-1!==e.firstTabInLine)return!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=i),a=e.input.charCodeAt(e.position);0!==a&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,x(e,"tab characters must not be used in indentation")),45===a)&&k(e.input.charCodeAt(e.position+1));)if(s=!0,e.position++,D(e,!0,-1)&&e.lineIndent<=t)i.push(null),a=e.input.charCodeAt(e.position);else if(n=e.line,j(e,t,Z,!1,!0),i.push(e.result),D(e,!0,-1),a=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==a)x(e,"bad indentation of a sequence entry");else if(e.lineIndentt?f=1:e.lineIndent===t?f=0:e.lineIndentt?f=1:e.lineIndent===t?f=0:e.lineIndentt)&&(y&&(i=e.line,s=e.lineStart,l=e.position),j(e,t,_,!0,r)&&(y?m=e.result:g=e.result),y||(L(e,f,p,h,m,g,i,s,l),h=m=g=null),D(e,!0,-1),u=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==u)x(e,"bad indentation of a mapping entry");else if(e.lineIndentl&&(l=e.lineIndent),w(d))u++;else{if(e.lineIndent=t){i=!0,f=e.input.charCodeAt(e.position);continue}e.position=o,e.line=s,e.lineStart=l,e.lineIndent=u;break}}i&&(T(e,r,o,!1),P(e,e.line-s),r=o=e.position,i=!1),M(f)||(o=e.position+1),f=e.input.charCodeAt(++e.position)}if(T(e,r,o,!1),e.result)return 1;e.kind=c,e.result=d}}(e,a,v===n)&&(h=!0,null===e.tag)&&(e.tag="?"):(h=!0,null===e.tag&&null===e.anchor||x(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===f&&(h=s&&ge(e,r))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&x(e,'unacceptable node kind for ! tag; it should be "scalar", not "'+e.kind+'"'),l=0,u=e.implicitTypes.length;l"),null!==e.result&&d.kind!==e.kind&&x(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+d.kind+'", not "'+e.kind+'"'),d.resolve(e.result,e.tag)?(e.result=d.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):x(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||h}function ye(e,t){t=t||{};var n=new de(e=0!==(e=String(e)).length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+="\n"),65279===e.charCodeAt(0))?e.slice(1):e,t),t=e.indexOf("\0");for(-1!==t&&(n.position=t,x(n,"null byte is not allowed in input")),n.input+="\0";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.positiondocument.F=Object<\/script>"),e.close(),u=e.F;t--;)delete u[l][i[t]];return u()};e.exports=Object.create||function(e,t){var n;return null!==e?(a[l]=r(e),n=new a,a[l]=null,n[s]=e):n=u(),void 0===t?n:o(n,t)}},function(e,t,n){var a=n(89).f,r=n(90),o=n(100)("toStringTag");e.exports=function(e,t,n){e&&!r(e=n?e:e.prototype,o)&&a(e,o,{configurable:!0,value:t})}},function(e,t,n){t.f=n(100)},function(e,t,n){var a=n(80),r=n(81),o=n(128),i=n(162),s=n(89).f;e.exports=function(e){var t=r.Symbol||(r.Symbol=!o&&a.Symbol||{});"_"==e.charAt(0)||e in t||s(t,e,{value:i.f(e)})}},function(e,t,n){"use strict";t.__esModule=!0;var a=c(n(219)),r=c(n(520)),o=c(n(521)),i=c(n(522)),s=c(n(523)),l=c(n(524)),u=c(n(525));function c(e){return e&&e.__esModule?e:{default:e}}n(526),a.default.extend(l.default),a.default.extend(s.default),a.default.extend(r.default),a.default.extend(o.default),a.default.extend(i.default),a.default.extend(u.default),a.default.locale("zh-cn");n=a.default;n.isSelf=a.default.isDayjs,a.default.localeData(),t.default=n,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var v=d(n(3)),o=d(n(4)),i=d(n(7)),a=d(n(8)),r=n(0),_=d(r),s=d(n(5)),l=n(31),b=d(n(19)),u=d(n(44)),w=d(n(26)),M=d(n(83)),c=d(n(6)),k=n(11);function d(e){return e&&e.__esModule?e:{default:e}}function f(){}p=r.Component,(0,a.default)(S,p),S.getDerivedStateFromProps=function(e){return"visible"in e?{visible:e.visible}:{}},S.prototype.render=function(){var e,t=this.props,n=t.prefix,a=(t.pure,t.className),r=t.style,o=t.type,i=t.shape,s=t.size,l=t.title,u=t.children,c=(t.defaultVisible,t.visible,t.iconType),d=t.closeable,f=(t.onClose,t.afterClose),p=t.animation,h=t.rtl,t=t.locale,m=(0,v.default)({},k.obj.pickOthers(Object.keys(S.propTypes),this.props)),g=this.state.visible,y=n+"message",o=(0,b.default)(((e={})[y]=!0,e[n+"message-"+o]=o,e[""+n+i]=i,e[""+n+s]=s,e[n+"title-content"]=!!l,e[n+"only-content"]=!l&&!!u,e[a]=a,e)),i=g?_.default.createElement("div",(0,v.default)({role:"alert",style:r},m,{className:o,dir:h?"rtl":void 0}),d?_.default.createElement("a",{role:"button","aria-label":t.closeAriaLabel,className:y+"-close",onClick:this.onClose},_.default.createElement(w.default,{type:"close"})):null,!1!==c?_.default.createElement(w.default,{className:y+"-symbol "+(!c&&y+"-symbol-icon"),type:c}):null,l?_.default.createElement("div",{className:y+"-title"},l):null,u?_.default.createElement("div",{className:y+"-content"},u):null):null;return p?_.default.createElement(M.default.Expand,{animationAppear:!1,afterLeave:f},i):i},r=n=S,n.propTypes={prefix:s.default.string,pure:s.default.bool,className:s.default.string,style:s.default.object,type:s.default.oneOf(["success","warning","error","notice","help","loading"]),shape:s.default.oneOf(["inline","addon","toast"]),size:s.default.oneOf(["medium","large"]),title:s.default.node,children:s.default.node,defaultVisible:s.default.bool,visible:s.default.bool,iconType:s.default.oneOfType([s.default.string,s.default.bool]),closeable:s.default.bool,onClose:s.default.func,afterClose:s.default.func,animation:s.default.bool,locale:s.default.object,rtl:s.default.bool},n.defaultProps={prefix:"next-",pure:!1,type:"success",shape:"inline",size:"medium",defaultVisible:!0,closeable:!1,onClose:f,afterClose:f,animation:!0,locale:u.default.Message};var p,a=r;function S(){var e,t;(0,o.default)(this,S);for(var n=arguments.length,a=Array(n),r=0;r=n.length?(l=!!(d=h(o,u)))&&"get"in d&&!("originalValue"in d.get)?d.get:o[u]:(l=_(o,u),o[u]),l&&!i&&(g[c]=o)}}return o}},function(e,t,n){"use strict";n=n(625);e.exports=Function.prototype.bind||n},function(e,t,n){"use strict";var a=String.prototype.replace,r=/%20/g,o="RFC1738",i="RFC3986";e.exports={default:i,formatters:{RFC1738:function(e){return a.call(e,r,"+")},RFC3986:function(e){return String(e)}},RFC1738:o,RFC3986:i}},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var c=l(n(3)),a=l(n(4)),r=l(n(7)),o=l(n(8)),d=n(0),f=l(d),i=l(n(5)),p=l(n(19)),h=l(n(26)),s=n(11),m=l(n(104));function l(e){return e&&e.__esModule?e:{default:e}}var u,g=s.func.bindCtx,y=s.obj.pickOthers,i=(u=d.Component,(0,o.default)(v,u),v.prototype.getSelected=function(){var e=this.props,t=e._key,n=e.root,e=e.selected,a=n.props.selectMode,n=n.state.selectedKeys;return e||!!a&&-1e.length&&e.every(function(e,t){return e===n[t]})},t.isAvailablePos=function(e,t,n){var n=n[t],a=n.type,n=n.disabled;return r(e,t)&&("item"===a&&!n||"submenu"===a)});t.getFirstAvaliablelChildKey=function(t,n){var e=Object.keys(n).find(function(e){return a(t+"-0",e,n)});return e?n[e].key:null},t.getChildSelected=function(e){var t,n=e.selectMode,a=e.selectedKeys,r=e._k2n,e=e._key;return!!r&&(t=(r[e]&&r[e].pos)+"-",!!n)&&a.some(function(e){return r[e]&&0===r[e].pos.indexOf(t)})}},function(e,t,n){"use strict";n(43),n(72),n(654)},function(e,t,n){"use strict";t.__esModule=!0;var g=d(n(17)),y=d(n(3)),a=d(n(4)),r=d(n(7)),o=d(n(8)),i=n(0),v=d(i),s=d(n(5)),_=d(n(19)),l=d(n(83)),u=d(n(26)),b=n(11),c=d(n(44)),n=d(n(6));function d(e){return e&&e.__esModule?e:{default:e}}var f,p=b.func.noop,h=b.func.bindCtx,m=/blue|green|orange|red|turquoise|yellow/,s=(f=i.Component,(0,o.default)(w,f),w.prototype.componentWillUnmount=function(){this.__destroyed=!0},w.prototype.handleClose=function(e){var t=this,n=this.props,a=n.animation,n=n.onClose,r=b.support.animation&&a;!1===n(e,this.tagNode)||this.__destroyed||this.setState({visible:!1},function(){r||t.props.afterClose(t.tagNode)})},w.prototype.handleBodyClick=function(e){var t=this.props,n=t.closable,a=t.closeArea,t=t.onClick,r=e.currentTarget;if(r&&(r===e.target||r.contains(e.target))&&(n&&"tag"===a&&this.handleClose("tag"),"function"==typeof t))return t(e)},w.prototype.handleTailClick=function(e){e&&e.preventDefault(),e&&e.stopPropagation(),this.handleClose("tail")},w.prototype.handleAnimationInit=function(e){this.props.afterAppear(e)},w.prototype.handleAnimationEnd=function(e){this.props.afterClose(e)},w.prototype.renderAnimatedTag=function(e,t){return v.default.createElement(l.default,{animation:t,afterAppear:this.handleAnimationInit,afterLeave:this.handleAnimationEnd},e)},w.prototype.renderTailNode=function(){var e=this.props,t=e.prefix,n=e.closable,e=e.locale;return n?v.default.createElement("span",{className:t+"tag-close-btn",onClick:this.handleTailClick,role:"button","aria-label":e.delete},v.default.createElement(u.default,{type:"close"})):null},w.prototype.isPresetColor=function(){var e=this.props.color;return!!e&&m.test(e)},w.prototype.getTagStyle=function(){var e=this.props,t=e.color,t=void 0===t?"":t,e=e.style,n=this.isPresetColor();return(0,y.default)({},t&&!n?{backgroundColor:t,borderColor:t,color:"#fff"}:null,e)},w.prototype.render=function(){var t=this,e=this.props,n=e.prefix,a=e.type,r=e.size,o=e.color,i=e._shape,s=e.closable,l=e.closeArea,u=e.className,c=e.children,d=e.animation,f=e.disabled,e=e.rtl,p=this.state.visible,h=this.isPresetColor(),m=b.obj.pickOthers(w.propTypes,this.props),m=(m.style,(0,g.default)(m,["style"])),r=(0,_.default)([n+"tag",n+"tag-"+(s?"closable":i),n+"tag-"+r],((i={})[n+"tag-level-"+a]=!o,i[n+"tag-closable"]=s,i[n+"tag-body-pointer"]=s&&"tag"===l,i[n+"tag-"+o]=o&&h&&"primary"===a,i[n+"tag-"+o+"-inverse"]=o&&h&&"normal"===a,i),u),s=this.renderTailNode(),l=p?v.default.createElement("div",(0,y.default)({className:r,onClick:this.handleBodyClick,onKeyDown:this.onKeyDown,tabIndex:f?"":"0",role:"button","aria-disabled":f,disabled:f,dir:e?"rtl":void 0,ref:function(e){return t.tagNode=e},style:this.getTagStyle()},m),v.default.createElement("span",{className:n+"tag-body"},c),s):null;return d&&b.support.animation?this.renderAnimatedTag(l,n+"tag-zoom"):l},o=i=w,i.propTypes={prefix:s.default.string,type:s.default.oneOf(["normal","primary"]),size:s.default.oneOf(["small","medium","large"]),color:s.default.string,animation:s.default.bool,closeArea:s.default.oneOf(["tag","tail"]),closable:s.default.bool,onClose:s.default.func,afterClose:s.default.func,afterAppear:s.default.func,className:s.default.any,children:s.default.node,onClick:s.default.func,_shape:s.default.oneOf(["default","closable","checkable"]),disabled:s.default.bool,rtl:s.default.bool,locale:s.default.object},i.defaultProps={prefix:"next-",type:"normal",size:"medium",closeArea:"tail",animation:!1,onClose:p,afterClose:p,afterAppear:p,onClick:p,_shape:"default",disabled:!1,rtl:!1,locale:c.default.Tag},o);function w(e){(0,a.default)(this,w);var o=(0,r.default)(this,f.call(this,e));return o.onKeyDown=function(e){var t=o.props,n=t.closable,a=t.closeArea,r=t.onClick,t=t.disabled;e.keyCode!==b.KEYCODE.SPACE||t||(e.preventDefault(),e.stopPropagation(),n?o.handleClose(a):"function"==typeof r&&r(e))},o.state={visible:!0},h(o,["handleBodyClick","handleTailClick","handleAnimationInit","handleAnimationEnd","renderTailNode"]),o}s.displayName="Tag",t.default=n.default.config(s),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var f=r(n(17)),p=r(n(42)),h=r(n(3)),a=(t.isSingle=function(e){return!e||"single"===e},t.isNull=s,t.escapeForReg=o,t.filter=function(e,t){e=o(""+e),e=new RegExp("("+e+")","ig");return e.test(""+t.value)||e.test(""+t.label)},t.loopMap=i,t.parseDataSourceFromChildren=function i(e){var s=1{var t=new TomlError(e.message);return t.code=e.code,t.wrapped=e,t},module.exports.TomlError=TomlError;const createDateTime=__webpack_require__(697),createDateTimeFloat=__webpack_require__(698),createDate=__webpack_require__(699),createTime=__webpack_require__(700),CTRL_I=9,CTRL_J=10,CTRL_M=13,CTRL_CHAR_BOUNDARY=31,CHAR_SP=32,CHAR_QUOT=34,CHAR_NUM=35,CHAR_APOS=39,CHAR_PLUS=43,CHAR_COMMA=44,CHAR_HYPHEN=45,CHAR_PERIOD=46,CHAR_0=48,CHAR_1=49,CHAR_7=55,CHAR_9=57,CHAR_COLON=58,CHAR_EQUALS=61,CHAR_A=65,CHAR_E=69,CHAR_F=70,CHAR_T=84,CHAR_U=85,CHAR_Z=90,CHAR_LOWBAR=95,CHAR_a=97,CHAR_b=98,CHAR_e=101,CHAR_f=102,CHAR_i=105,CHAR_l=108,CHAR_n=110,CHAR_o=111,CHAR_r=114,CHAR_s=115,CHAR_t=116,CHAR_u=117,CHAR_x=120,CHAR_z=122,CHAR_LCUB=123,CHAR_RCUB=125,CHAR_LSQB=91,CHAR_BSOL=92,CHAR_RSQB=93,CHAR_DEL=127,SURROGATE_FIRST=55296,SURROGATE_LAST=57343,escapes={[CHAR_b]:"\b",[CHAR_t]:"\t",[CHAR_n]:"\n",[CHAR_f]:"\f",[CHAR_r]:"\r",[CHAR_QUOT]:'"',[CHAR_BSOL]:"\\"};function isDigit(e){return e>=CHAR_0&&e<=CHAR_9}function isHexit(e){return e>=CHAR_A&&e<=CHAR_F||e>=CHAR_a&&e<=CHAR_f||e>=CHAR_0&&e<=CHAR_9}function isBit(e){return e===CHAR_1||e===CHAR_0}function isOctit(e){return e>=CHAR_0&&e<=CHAR_7}function isAlphaNumQuoteHyphen(e){return e>=CHAR_A&&e<=CHAR_Z||e>=CHAR_a&&e<=CHAR_z||e>=CHAR_0&&e<=CHAR_9||e===CHAR_APOS||e===CHAR_QUOT||e===CHAR_LOWBAR||e===CHAR_HYPHEN}function isAlphaNumHyphen(e){return e>=CHAR_A&&e<=CHAR_Z||e>=CHAR_a&&e<=CHAR_z||e>=CHAR_0&&e<=CHAR_9||e===CHAR_LOWBAR||e===CHAR_HYPHEN}const _type=Symbol("type"),_declared=Symbol("declared"),hasOwnProperty=Object.prototype.hasOwnProperty,defineProperty=Object.defineProperty,descriptor={configurable:!0,enumerable:!0,writable:!0,value:void 0};function hasKey(e,t){if(hasOwnProperty.call(e,t))return 1;"__proto__"===t&&defineProperty(e,"__proto__",descriptor)}const INLINE_TABLE=Symbol("inline-table");function InlineTable(){return Object.defineProperties({},{[_type]:{value:INLINE_TABLE}})}function isInlineTable(e){return null!==e&&"object"==typeof e&&e[_type]===INLINE_TABLE}const TABLE=Symbol("table");function Table(){return Object.defineProperties({},{[_type]:{value:TABLE},[_declared]:{value:!1,writable:!0}})}function isTable(e){return null!==e&&"object"==typeof e&&e[_type]===TABLE}const _contentType=Symbol("content-type"),INLINE_LIST=Symbol("inline-list");function InlineList(e){return Object.defineProperties([],{[_type]:{value:INLINE_LIST},[_contentType]:{value:e}})}function isInlineList(e){return null!==e&&"object"==typeof e&&e[_type]===INLINE_LIST}const LIST=Symbol("list");function List(){return Object.defineProperties([],{[_type]:{value:LIST}})}function isList(e){return null!==e&&"object"==typeof e&&e[_type]===LIST}let _custom;try{const utilInspect=eval("require('util').inspect");_custom=utilInspect.custom}catch(_){}const _inspect=_custom||"inspect";class BoxedBigInt{constructor(e){try{this.value=global.BigInt.asIntN(64,e)}catch(e){this.value=null}Object.defineProperty(this,_type,{value:INTEGER})}isNaN(){return null===this.value}toString(){return String(this.value)}[_inspect](){return`[BigInt: ${this.toString()}]}`}valueOf(){return this.value}}const INTEGER=Symbol("integer");function Integer(e){let t=Number(e);return Object.is(t,-0)&&(t=0),global.BigInt&&!Number.isSafeInteger(t)?new BoxedBigInt(e):Object.defineProperties(new Number(t),{isNaN:{value:function(){return isNaN(this)}},[_type]:{value:INTEGER},[_inspect]:{value:()=>`[Integer: ${e}]`}})}function isInteger(e){return null!==e&&"object"==typeof e&&e[_type]===INTEGER}const FLOAT=Symbol("float");function Float(e){return Object.defineProperties(new Number(e),{[_type]:{value:FLOAT},[_inspect]:{value:()=>`[Float: ${e}]`}})}function isFloat(e){return null!==e&&"object"==typeof e&&e[_type]===FLOAT}function tomlType(e){var t=typeof e;if("object"==t){if(null===e)return"null";if(e instanceof Date)return"datetime";if(_type in e)switch(e[_type]){case INLINE_TABLE:return"inline-table";case INLINE_LIST:return"inline-list";case TABLE:return"table";case LIST:return"list";case FLOAT:return"float";case INTEGER:return"integer"}}return t}function makeParserClass(e){class t extends e{constructor(){super(),this.ctx=this.obj=Table()}atEndOfWord(){return this.char===CHAR_NUM||this.char===CTRL_I||this.char===CHAR_SP||this.atEndOfLine()}atEndOfLine(){return this.char===e.END||this.char===CTRL_J||this.char===CTRL_M}parseStart(){if(this.char===e.END)return null;if(this.char===CHAR_LSQB)return this.call(this.parseTableOrList);if(this.char===CHAR_NUM)return this.call(this.parseComment);if(this.char===CTRL_J||this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M)return null;if(isAlphaNumQuoteHyphen(this.char))return this.callNow(this.parseAssignStatement);throw this.error(new TomlError(`Unknown character "${this.char}"`))}parseWhitespaceToEOL(){if(this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M)return null;if(this.char===CHAR_NUM)return this.goto(this.parseComment);if(this.char===e.END||this.char===CTRL_J)return this.return();throw this.error(new TomlError("Unexpected character, expected only whitespace or comments till end of line"))}parseAssignStatement(){return this.callNow(this.parseAssign,this.recordAssignStatement)}recordAssignStatement(e){let t=this.ctx;var n,a=e.key.pop();for(n of e.key){if(hasKey(t,n)&&!isTable(t[n]))throw this.error(new TomlError("Can't redefine existing key"));t=t[n]=t[n]||Table()}if(hasKey(t,a))throw this.error(new TomlError("Can't redefine existing key"));return t[_declared]=!0,isInteger(e.value)||isFloat(e.value)?t[a]=e.value.valueOf():t[a]=e.value,this.goto(this.parseWhitespaceToEOL)}parseAssign(){return this.callNow(this.parseKeyword,this.recordAssignKeyword)}recordAssignKeyword(e){return this.state.resultTable?this.state.resultTable.push(e):this.state.resultTable=[e],this.goto(this.parseAssignKeywordPreDot)}parseAssignKeywordPreDot(){return this.char===CHAR_PERIOD?this.next(this.parseAssignKeywordPostDot):this.char!==CHAR_SP&&this.char!==CTRL_I?this.goto(this.parseAssignEqual):void 0}parseAssignKeywordPostDot(){if(this.char!==CHAR_SP&&this.char!==CTRL_I)return this.callNow(this.parseKeyword,this.recordAssignKeyword)}parseAssignEqual(){if(this.char===CHAR_EQUALS)return this.next(this.parseAssignPreValue);throw this.error(new TomlError('Invalid character, expected "="'))}parseAssignPreValue(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseValue,this.recordAssignValue)}recordAssignValue(e){return this.returnNow({key:this.state.resultTable,value:e})}parseComment(){do{if(this.char===e.END||this.char===CTRL_J)return this.return();if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("comments")}while(this.nextChar())}parseTableOrList(){if(this.char!==CHAR_LSQB)return this.goto(this.parseTable);this.next(this.parseList)}parseTable(){return this.ctx=this.obj,this.goto(this.parseTableNext)}parseTableNext(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseKeyword,this.parseTableMore)}parseTableMore(e){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CHAR_RSQB){if(!hasKey(this.ctx,e)||isTable(this.ctx[e])&&!this.ctx[e][_declared])return this.ctx=this.ctx[e]=this.ctx[e]||Table(),this.ctx[_declared]=!0,this.next(this.parseWhitespaceToEOL);throw this.error(new TomlError("Can't redefine existing key"))}if(this.char!==CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));if(hasKey(this.ctx,e))if(isTable(this.ctx[e]))this.ctx=this.ctx[e];else{if(!isList(this.ctx[e]))throw this.error(new TomlError("Can't redefine existing key"));this.ctx=this.ctx[e][this.ctx[e].length-1]}else this.ctx=this.ctx[e]=Table();return this.next(this.parseTableNext)}parseList(){return this.ctx=this.obj,this.goto(this.parseListNext)}parseListNext(){return this.char===CHAR_SP||this.char===CTRL_I?null:this.callNow(this.parseKeyword,this.parseListMore)}parseListMore(e){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CHAR_RSQB){if(hasKey(this.ctx,e)||(this.ctx[e]=List()),isInlineList(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline array"));var t;if(isList(this.ctx[e]))return t=Table(),this.ctx[e].push(t),this.ctx=t,this.next(this.parseListEnd);throw this.error(new TomlError("Can't redefine an existing key"))}if(this.char!==CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"));if(hasKey(this.ctx,e)){if(isInlineList(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline array"));if(isInlineTable(this.ctx[e]))throw this.error(new TomlError("Can't extend an inline table"));if(isList(this.ctx[e]))this.ctx=this.ctx[e][this.ctx[e].length-1];else{if(!isTable(this.ctx[e]))throw this.error(new TomlError("Can't redefine an existing key"));this.ctx=this.ctx[e]}}else this.ctx=this.ctx[e]=Table();return this.next(this.parseListNext)}parseListEnd(e){if(this.char===CHAR_RSQB)return this.next(this.parseWhitespaceToEOL);throw this.error(new TomlError("Unexpected character, expected whitespace, . or ]"))}parseValue(){if(this.char===e.END)throw this.error(new TomlError("Key without value"));if(this.char===CHAR_QUOT)return this.next(this.parseDoubleString);if(this.char===CHAR_APOS)return this.next(this.parseSingleString);if(this.char===CHAR_HYPHEN||this.char===CHAR_PLUS)return this.goto(this.parseNumberSign);if(this.char===CHAR_i)return this.next(this.parseInf);if(this.char===CHAR_n)return this.next(this.parseNan);if(isDigit(this.char))return this.goto(this.parseNumberOrDateTime);if(this.char===CHAR_t||this.char===CHAR_f)return this.goto(this.parseBoolean);if(this.char===CHAR_LSQB)return this.call(this.parseInlineList,this.recordValue);if(this.char===CHAR_LCUB)return this.call(this.parseInlineTable,this.recordValue);throw this.error(new TomlError("Unexpected character, expecting string, number, datetime, boolean, inline array or inline table"))}recordValue(e){return this.returnNow(e)}parseInf(){if(this.char===CHAR_n)return this.next(this.parseInf2);throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'))}parseInf2(){if(this.char===CHAR_f)return"-"===this.state.buf?this.return(-1/0):this.return(1/0);throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"'))}parseNan(){if(this.char===CHAR_a)return this.next(this.parseNan2);throw this.error(new TomlError('Unexpected character, expected "nan"'))}parseNan2(){if(this.char===CHAR_n)return this.return(NaN);throw this.error(new TomlError('Unexpected character, expected "nan"'))}parseKeyword(){return this.char===CHAR_QUOT?this.next(this.parseBasicString):this.char===CHAR_APOS?this.next(this.parseLiteralString):this.goto(this.parseBareKey)}parseBareKey(){do{if(this.char===e.END)throw this.error(new TomlError("Key ended without value"));if(!isAlphaNumHyphen(this.char)){if(0===this.state.buf.length)throw this.error(new TomlError("Empty bare keys are not allowed"));return this.returnNow()}}while(this.consume(),this.nextChar())}parseSingleString(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiStringMaybe):this.goto(this.parseLiteralString)}parseLiteralString(){do{if(this.char===CHAR_APOS)return this.return();if(this.atEndOfLine())throw this.error(new TomlError("Unterminated string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}parseLiteralMultiStringMaybe(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiString):this.returnNow()}parseLiteralMultiString(){return this.char===CTRL_M?null:this.char===CTRL_J?this.next(this.parseLiteralMultiStringContent):this.goto(this.parseLiteralMultiStringContent)}parseLiteralMultiStringContent(){do{if(this.char===CHAR_APOS)return this.next(this.parseLiteralMultiEnd);if(this.char===e.END)throw this.error(new TomlError("Unterminated multi-line string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I&&this.char!==CTRL_J&&this.char!==CTRL_M)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}parseLiteralMultiEnd(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiEnd2):(this.state.buf+="'",this.goto(this.parseLiteralMultiStringContent))}parseLiteralMultiEnd2(){return this.char===CHAR_APOS?this.next(this.parseLiteralMultiEnd3):(this.state.buf+="''",this.goto(this.parseLiteralMultiStringContent))}parseLiteralMultiEnd3(){return this.char===CHAR_APOS?(this.state.buf+="'",this.next(this.parseLiteralMultiEnd4)):this.returnNow()}parseLiteralMultiEnd4(){return this.char===CHAR_APOS?(this.state.buf+="'",this.return()):this.returnNow()}parseDoubleString(){return this.char===CHAR_QUOT?this.next(this.parseMultiStringMaybe):this.goto(this.parseBasicString)}parseBasicString(){do{if(this.char===CHAR_BSOL)return this.call(this.parseEscape,this.recordEscapeReplacement);if(this.char===CHAR_QUOT)return this.return();if(this.atEndOfLine())throw this.error(new TomlError("Unterminated string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}recordEscapeReplacement(e){return this.state.buf+=e,this.goto(this.parseBasicString)}parseMultiStringMaybe(){return this.char===CHAR_QUOT?this.next(this.parseMultiString):this.returnNow()}parseMultiString(){return this.char===CTRL_M?null:this.char===CTRL_J?this.next(this.parseMultiStringContent):this.goto(this.parseMultiStringContent)}parseMultiStringContent(){do{if(this.char===CHAR_BSOL)return this.call(this.parseMultiEscape,this.recordMultiEscapeReplacement);if(this.char===CHAR_QUOT)return this.next(this.parseMultiEnd);if(this.char===e.END)throw this.error(new TomlError("Unterminated multi-line string"));if(this.char===CHAR_DEL||this.char<=CTRL_CHAR_BOUNDARY&&this.char!==CTRL_I&&this.char!==CTRL_J&&this.char!==CTRL_M)throw this.errorControlCharIn("strings")}while(this.consume(),this.nextChar())}errorControlCharIn(e){let t="\\u00";return this.char<16&&(t+="0"),t+=this.char.toString(16),this.error(new TomlError(`Control characters (codes < 0x1f and 0x7f) are not allowed in ${e}, use ${t} instead`))}recordMultiEscapeReplacement(e){return this.state.buf+=e,this.goto(this.parseMultiStringContent)}parseMultiEnd(){return this.char===CHAR_QUOT?this.next(this.parseMultiEnd2):(this.state.buf+='"',this.goto(this.parseMultiStringContent))}parseMultiEnd2(){return this.char===CHAR_QUOT?this.next(this.parseMultiEnd3):(this.state.buf+='""',this.goto(this.parseMultiStringContent))}parseMultiEnd3(){return this.char===CHAR_QUOT?(this.state.buf+='"',this.next(this.parseMultiEnd4)):this.returnNow()}parseMultiEnd4(){return this.char===CHAR_QUOT?(this.state.buf+='"',this.return()):this.returnNow()}parseMultiEscape(){return this.char===CTRL_M||this.char===CTRL_J?this.next(this.parseMultiTrim):this.char===CHAR_SP||this.char===CTRL_I?this.next(this.parsePreMultiTrim):this.goto(this.parseEscape)}parsePreMultiTrim(){if(this.char===CHAR_SP||this.char===CTRL_I)return null;if(this.char===CTRL_M||this.char===CTRL_J)return this.next(this.parseMultiTrim);throw this.error(new TomlError("Can't escape whitespace"))}parseMultiTrim(){return this.char===CTRL_J||this.char===CHAR_SP||this.char===CTRL_I||this.char===CTRL_M?null:this.returnNow()}parseEscape(){if(this.char in escapes)return this.return(escapes[this.char]);if(this.char===CHAR_u)return this.call(this.parseSmallUnicode,this.parseUnicodeReturn);if(this.char===CHAR_U)return this.call(this.parseLargeUnicode,this.parseUnicodeReturn);throw this.error(new TomlError("Unknown escape character: "+this.char))}parseUnicodeReturn(e){try{var t=parseInt(e,16);if(t>=SURROGATE_FIRST&&t<=SURROGATE_LAST)throw this.error(new TomlError("Invalid unicode, character in range 0xD800 - 0xDFFF is reserved"));return this.returnNow(String.fromCodePoint(t))}catch(e){throw this.error(TomlError.wrap(e))}}parseSmallUnicode(){if(!isHexit(this.char))throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"));if(this.consume(),4<=this.state.buf.length)return this.return()}parseLargeUnicode(){if(!isHexit(this.char))throw this.error(new TomlError("Invalid character in unicode sequence, expected hex"));if(this.consume(),8<=this.state.buf.length)return this.return()}parseNumberSign(){return this.consume(),this.next(this.parseMaybeSignedInfOrNan)}parseMaybeSignedInfOrNan(){return this.char===CHAR_i?this.next(this.parseInf):this.char===CHAR_n?this.next(this.parseNan):this.callNow(this.parseNoUnder,this.parseNumberIntegerStart)}parseNumberIntegerStart(){return this.char===CHAR_0?(this.consume(),this.next(this.parseNumberIntegerExponentOrDecimal)):this.goto(this.parseNumberInteger)}parseNumberIntegerExponentOrDecimal(){return this.char===CHAR_PERIOD?(this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat)):this.char===CHAR_E||this.char===CHAR_e?(this.consume(),this.next(this.parseNumberExponentSign)):this.returnNow(Integer(this.state.buf))}parseNumberInteger(){if(!isDigit(this.char)){if(this.char===CHAR_LOWBAR)return this.call(this.parseNoUnder);if(this.char===CHAR_E||this.char===CHAR_e)return this.consume(),this.next(this.parseNumberExponentSign);if(this.char===CHAR_PERIOD)return this.consume(),this.call(this.parseNoUnder,this.parseNumberFloat);var e=Integer(this.state.buf);if(e.isNaN())throw this.error(new TomlError("Invalid number"));return this.returnNow(e)}this.consume()}parseNoUnder(){if(this.char===CHAR_LOWBAR||this.char===CHAR_PERIOD||this.char===CHAR_E||this.char===CHAR_e)throw this.error(new TomlError("Unexpected character, expected digit"));if(this.atEndOfWord())throw this.error(new TomlError("Incomplete number"));return this.returnNow()}parseNoUnderHexOctBinLiteral(){if(this.char===CHAR_LOWBAR||this.char===CHAR_PERIOD)throw this.error(new TomlError("Unexpected character, expected digit"));if(this.atEndOfWord())throw this.error(new TomlError("Incomplete number"));return this.returnNow()}parseNumberFloat(){return this.char===CHAR_LOWBAR?this.call(this.parseNoUnder,this.parseNumberFloat):isDigit(this.char)?void this.consume():this.char===CHAR_E||this.char===CHAR_e?(this.consume(),this.next(this.parseNumberExponentSign)):this.returnNow(Float(this.state.buf))}parseNumberExponentSign(){if(isDigit(this.char))return this.goto(this.parseNumberExponent);if(this.char!==CHAR_HYPHEN&&this.char!==CHAR_PLUS)throw this.error(new TomlError("Unexpected character, expected -, + or digit"));this.consume(),this.call(this.parseNoUnder,this.parseNumberExponent)}parseNumberExponent(){if(!isDigit(this.char))return this.char===CHAR_LOWBAR?this.call(this.parseNoUnder):this.returnNow(Float(this.state.buf));this.consume()}parseNumberOrDateTime(){return this.char===CHAR_0?(this.consume(),this.next(this.parseNumberBaseOrDateTime)):this.goto(this.parseNumberOrDateTimeOnly)}parseNumberOrDateTimeOnly(){return this.char===CHAR_LOWBAR?this.call(this.parseNoUnder,this.parseNumberInteger):isDigit(this.char)?(this.consume(),void(4{for(t=String(t);t.length "+o[t]+"\n")+(n+" ");for(let e=0;er&&!o.warned&&(o.warned=!0,(a=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit")).name="MaxListenersExceededWarning",a.emitter=e,a.type=t,a.count=o.length,n=a,console)&&console.warn&&console.warn(n)),e}function f(e,t,n){e={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},t=function(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}.bind(e);return t.listener=n,e.wrapFn=t}function p(e,t,n){e=e._events;if(void 0===e)return[];e=e[t];if(void 0===e)return[];if("function"==typeof e)return n?[e.listener||e]:[e];if(n){for(var a=e,r=new Array(a.length),o=0;o=u,u=(0,D.default)(((u={})[n+"upload-inner"]=!0,u[n+"hidden"]=x,u)),C=this.props.children;return"card"===r&&(r=(0,D.default)(((r={})[n+"upload-card"]=!0,r[n+"disabled"]=l,r)),C=O.default.createElement("div",{className:r},O.default.createElement(P.default,{size:"large",type:"add",className:n+"upload-add-icon"}),O.default.createElement("div",{tabIndex:"0",role:"button",className:n+"upload-text"},C))),b?"function"==typeof w?(b=(0,D.default)(((r={})[n+"form-preview"]=!0,r[o]=!!o,r)),O.default.createElement("div",{style:i,className:b},w(this.state.value,this.props))):t?O.default.createElement(Y.default,{isPreview:!0,listType:t,style:i,className:o,value:this.state.value,onPreview:m}):null:(n=l?N.func.prevent:p,r=N.obj.pickAttrsWith(this.props,"data-"),O.default.createElement("div",(0,T.default)({className:f,style:i},r),O.default.createElement(j.default,(0,T.default)({},e,{name:M,beforeUpload:d,dragable:a,disabled:l||x,className:u,onSelect:this.onSelect,onDrop:this.onDrop,onProgress:this.onProgress,onSuccess:this.onSuccess,onError:this.onError,ref:this.saveUploaderRef}),C),t||g?O.default.createElement(Y.default,{useDataURL:s,fileNameRender:k,actionRender:S,uploader:this,listType:t,value:this.state.value,closable:c,onRemove:n,progressProps:v,onCancel:h,onPreview:m,extraRender:y,rtl:_,previewOnFileName:E}):null))},i=u=h,u.displayName="Upload",u.propTypes=(0,T.default)({},c.default.propTypes,Y.default.propTypes,{prefix:s.default.string.isRequired,action:s.default.string,value:s.default.array,defaultValue:s.default.array,shape:s.default.oneOf(["card"]),listType:s.default.oneOf(["text","image","card"]),list:s.default.any,name:s.default.string,data:s.default.oneOfType([s.default.object,s.default.func]),formatter:s.default.func,limit:s.default.number,timeout:s.default.number,dragable:s.default.bool,closable:s.default.bool,useDataURL:s.default.bool,disabled:s.default.bool,onSelect:s.default.func,onProgress:s.default.func,onChange:s.default.func,onSuccess:s.default.func,afterSelect:s.default.func,onRemove:s.default.func,onError:s.default.func,beforeUpload:s.default.func,onDrop:s.default.func,className:s.default.string,style:s.default.object,children:s.default.node,autoUpload:s.default.bool,request:s.default.func,progressProps:s.default.object,rtl:s.default.bool,isPreview:s.default.bool,renderPreview:s.default.func,fileKeyName:s.default.string,fileNameRender:s.default.func,actionRender:s.default.func,previewOnFileName:s.default.bool}),u.defaultProps=(0,T.default)({},c.default.defaultProps,{prefix:"next-",limit:1/0,autoUpload:!0,closable:!0,onSelect:n,onProgress:n,onChange:n,onSuccess:n,onRemove:n,onError:n,onDrop:n,beforeUpload:n,afterSelect:n,previewOnFileName:!1}),a=function(){var u=this;this.onSelect=function(e){var t,n,a=u.props,r=a.autoUpload,o=a.afterSelect,i=a.onSelect,a=a.limit,s=u.state.value.length+e.length,l=a-u.state.value.length;l<=0||(t=e=e.map(function(e){e=(0,d.fileToObject)(e);return e.state="selected",e}),n=[],ai||s+a.width>o):t<0||e<0||t+a.height>u.height||e+a.width>u.width}function L(e,t,n,a){var r=a.overlayInfo,a=a.containerInfo,n=n.split("");return 1===n.length&&n.push(""),t<0&&(n=[n[0].replace("t","b"),n[1].replace("b","t")]),e<0&&(n=[n[0].replace("l","r"),n[1].replace("r","l")]),t+r.height>a.height&&(n=[n[0].replace("b","t"),n[1].replace("t","b")]),(n=e+r.width>a.width?[n[0].replace("r","l"),n[1].replace("l","r")]:n).join("")}function O(e,t,n){var a=n.overlayInfo,n=n.containerInfo;return(t=t<0?0:t)+a.height>n.height&&(t=n.height-a.height),{left:e=(e=e<0?0:e)+a.width>n.width?n.width-a.width:e,top:t}}function be(e){var r,o,i,s,t,n,a,l,u,c,d,f=e.target,p=e.overlay,h=e.container,m=e.scrollNode,g=e.placement,y=e.placementOffset,y=void 0===y?0:y,v=e.points,v=void 0===v?["tl","bl"]:v,_=e.offset,_=void 0===_?[0,0]:_,b=e.position,b=void 0===b?"absolute":b,w=e.beforePosition,M=e.autoAdjust,M=void 0===M||M,k=e.autoHideScrollOverflow,k=void 0===k||k,e=e.rtl,S="offsetWidth"in(S=p)&&"offsetHeight"in S?{width:S.offsetWidth,height:S.offsetHeight}:{width:(S=S.getBoundingClientRect()).width,height:S.height},E=S.width,S=S.height;return"fixed"===b?(l={config:{placement:void 0,points:void 0},style:{position:b,left:_[0],top:_[1]}},w?w(l,{overlay:{node:p,width:E,height:S}}):l):(l=f.getBoundingClientRect(),r=l.width,o=l.height,i=l.left,s=l.top,t=(l=x(h)).left,l=l.top,u=h.scrollWidth,c=h.scrollHeight,n=h.scrollTop,a=h.scrollLeft,u=(l=C(g,t={targetInfo:{width:r,height:o,left:i,top:s},containerInfo:{left:t,top:l,width:u,height:c,scrollTop:n,scrollLeft:a},overlayInfo:{width:E,height:S},points:v,placementOffset:y,offset:_,container:h,rtl:e})).left,c=l.top,n=l.points,a=function(e){for(var t=e;t;){var n=he(t,"overflow");if(null!=n&&n.match(/auto|scroll|hidden/))return t;t=t.parentNode}return document.documentElement}(h),M&&g&&T(u,c,a,t)&&(g!==(v=L(u,c,g,t))&&(c=T(_=(y=C(v,t)).left,e=y.top,a,t)&&v!==(l=L(_,e,v,t))?(u=(M=O((h=C(g=l,t)).left,h.top,t)).left,M.top):(g=v,u=_,e)),u=(y=O(u,c,t)).left,c=y.top),d={config:{placement:g,points:n},style:{position:b,left:Math.round(u),top:Math.round(c)}},k&&g&&null!=m&&m.length&&m.forEach(function(e){var e=e.getBoundingClientRect(),t=e.top,n=e.left,a=e.width,e=e.height;d.style.display=s+o=e.length?{done:!0}:{done:!1,value:e[n++]}};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,a=new Array(t);nn.clientHeight&&0=11?e:e+12;else if(t==="下午"||t==="晚上")return e+12},meridiem:function(e,t,n){var a=e*100+t;if(a<600)return"凌晨";else if(a<900)return"早上";else if(a<1130)return"上午";else if(a<1230)return"中午";else if(a<1800)return"下午";else return"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(n(9))},function(e,t,n){!function(e){"use strict"; //! moment.js locale configuration -var t;e.defineLocale("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,t){if(e===12)e=0;if(t==="凌晨"||t==="早上"||t==="上午")return e;else if(t==="中午")return e>=11?e:e+12;else if(t==="下午"||t==="晚上")return e+12},meridiem:function(e,t,n){var a=e*100+t;if(a<600)return"凌晨";else if(a<900)return"早上";else if(a<1130)return"上午";else if(a<1230)return"中午";else if(a<1800)return"下午";else return"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(n(9))},function(e,t,n){"use strict";t.__esModule=!0;var u=p(n(3)),a=p(n(4)),r=p(n(7)),o=p(n(8)),i=n(0),c=p(i),s=p(n(5)),d=p(n(18)),l=p(n(6)),f=n(11);function p(e){return e&&e.__esModule?e:{default:e}}h=i.Component,(0,o.default)(m,h),m.prototype.render=function(){var e,t=this.props,n=t.prefix,a=t.type,r=t.size,o=t.className,i=t.rtl,s=t.style,t=t.children,l=f.obj.pickOthers((0,u.default)({},m.propTypes),this.props),n=(0,d.default)(((e={})[n+"icon"]=!0,e[n+"icon-"+a]=!!a,e[""+n+r]=!!r&&"string"==typeof r,e[o]=!!o,e)),o=(i&&-1!==["arrow-left","arrow-right","arrow-double-left","arrow-double-right","switch","sorting","descending","ascending"].indexOf(a)&&(l.dir="rtl"),"number"==typeof r?{width:r,height:r,lineHeight:r+"px",fontSize:r}:{});return c.default.createElement("i",(0,u.default)({},l,{style:(0,u.default)({},o,s),className:n}),t)},i=n=m,n.propTypes=(0,u.default)({},l.default.propTypes,{type:s.default.string,children:s.default.node,size:s.default.oneOfType([s.default.oneOf(["xxs","xs","small","medium","large","xl","xxl","xxxl","inherit"]),s.default.number]),className:s.default.string,style:s.default.object}),n.defaultProps={prefix:"next-",size:"medium"},n._typeMark="icon";var h,o=i;function m(){return(0,a.default)(this,m),(0,r.default)(this,h.apply(this,arguments))}o.displayName="Icon",t.default=o,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var g=l(n(3)),y=l(n(16)),a=l(n(42)),r=l(n(4)),o=l(n(7)),i=l(n(8)),v=n(0),_=l(v),s=l(n(5)),b=n(166),w=l(n(544));function l(e){return e&&e.__esModule?e:{default:e}}function u(){}function M(e){return _.default.Children.toArray(e.children)[0]||null}c=v.Component,(0,i.default)(d,c),d.prototype.normalizeNames=function(e){return"string"==typeof e?{appear:e+"-appear",appearActive:e+"-appear-active",enter:e+"-enter",enterActive:e+"-enter-active",leave:e+"-leave",leaveActive:e+"-leave-active"}:"object"===(void 0===e?"undefined":(0,a.default)(e))?{appear:e.appear,appearActive:e.appear+"-active",enter:""+e.enter,enterActive:e.enter+"-active",leave:""+e.leave,leaveActive:e.leave+"-active"}:void 0},d.prototype.render=function(){var t=this,e=this.props,n=e.animation,a=e.children,r=e.animationAppear,o=e.singleMode,i=e.component,s=e.beforeAppear,l=e.onAppear,u=e.afterAppear,c=e.beforeEnter,d=e.onEnter,f=e.afterEnter,p=e.beforeLeave,h=e.onLeave,m=e.afterLeave,e=(0,y.default)(e,["animation","children","animationAppear","singleMode","component","beforeAppear","onAppear","afterAppear","beforeEnter","onEnter","afterEnter","beforeLeave","onLeave","afterLeave"]),a=v.Children.map(a,function(e){return _.default.createElement(w.default,{key:e.key,names:t.normalizeNames(n),onAppear:s,onAppearing:l,onAppeared:u,onEnter:c,onEntering:d,onEntered:f,onExit:p,onExiting:h,onExited:m},e)});return _.default.createElement(b.TransitionGroup,(0,g.default)({appear:r,component:o?M:i},e),a)},i=n=d,n.propTypes={animation:s.default.oneOfType([s.default.string,s.default.object]),animationAppear:s.default.bool,component:s.default.any,singleMode:s.default.bool,children:s.default.oneOfType([s.default.element,s.default.arrayOf(s.default.element)]),beforeAppear:s.default.func,onAppear:s.default.func,afterAppear:s.default.func,beforeEnter:s.default.func,onEnter:s.default.func,afterEnter:s.default.func,beforeLeave:s.default.func,onLeave:s.default.func,afterLeave:s.default.func},n.defaultProps={animationAppear:!0,component:"div",singleMode:!0,beforeAppear:u,onAppear:u,afterAppear:u,beforeEnter:u,onEnter:u,afterEnter:u,beforeLeave:u,onLeave:u,afterLeave:u};var c,s=i;function d(){return(0,r.default)(this,d),(0,o.default)(this,c.apply(this,arguments))}s.displayName="Animate",t.default=s,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.default=t.EXITING=t.ENTERED=t.ENTERING=t.EXITED=t.UNMOUNTED=void 0;var a=function(e){{if(e&&e.__esModule)return e;var t,n={};if(null!=e)for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&((t=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,a):{}).get||t.set?Object.defineProperty(n,a,t):n[a]=e[a]);return n.default=e,n}}(n(5)),o=s(n(0)),i=s(n(25)),r=n(31);n(360);function s(e){return e&&e.__esModule?e:{default:e}}var l="unmounted",u=(t.UNMOUNTED=l,"exited"),c=(t.EXITED=u,"entering"),d=(t.ENTERING=c,"entered"),f=(t.ENTERED=d,"exiting"),n=(t.EXITING=f,function(r){var e;function t(e,t){var n,a=r.call(this,e,t)||this,t=t.transitionGroup,t=t&&!t.isMounting?e.enter:e.appear;return a.appearStatus=null,e.in?t?(n=u,a.appearStatus=c):n=d:n=e.unmountOnExit||e.mountOnEnter?l:u,a.state={status:n},a.nextCallback=null,a}e=r,(n=t).prototype=Object.create(e.prototype),(n.prototype.constructor=n).__proto__=e;var n=t.prototype;return n.getChildContext=function(){return{transitionGroup:null}},t.getDerivedStateFromProps=function(e,t){return e.in&&t.status===l?{status:u}:null},n.componentDidMount=function(){this.updateStatus(!0,this.appearStatus)},n.componentDidUpdate=function(e){var t=null;e!==this.props&&(e=this.state.status,this.props.in?e!==c&&e!==d&&(t=c):e!==c&&e!==d||(t=f)),this.updateStatus(!1,t)},n.componentWillUnmount=function(){this.cancelNextCallback()},n.getTimeouts=function(){var e,t,n=this.props.timeout,a=e=t=n;return null!=n&&"number"!=typeof n&&(a=n.exit,e=n.enter,t=void 0!==n.appear?n.appear:e),{exit:a,enter:e,appear:t}},n.updateStatus=function(e,t){var n;void 0===e&&(e=!1),null!==t?(this.cancelNextCallback(),n=i.default.findDOMNode(this),t===c?this.performEnter(n,e):this.performExit(n)):this.props.unmountOnExit&&this.state.status===u&&this.setState({status:l})},n.performEnter=function(e,t){var n=this,a=this.props.enter,r=this.context.transitionGroup?this.context.transitionGroup.isMounting:t,o=this.getTimeouts(),i=r?o.appear:o.enter;t||a?(this.props.onEnter(e,r),this.safeSetState({status:c},function(){n.props.onEntering(e,r),n.onTransitionEnd(e,i,function(){n.safeSetState({status:d},function(){n.props.onEntered(e,r)})})})):this.safeSetState({status:d},function(){n.props.onEntered(e)})},n.performExit=function(e){var t=this,n=this.props.exit,a=this.getTimeouts();n?(this.props.onExit(e),this.safeSetState({status:f},function(){t.props.onExiting(e),t.onTransitionEnd(e,a.exit,function(){t.safeSetState({status:u},function(){t.props.onExited(e)})})})):this.safeSetState({status:u},function(){t.props.onExited(e)})},n.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},n.safeSetState=function(e,t){t=this.setNextCallback(t),this.setState(e,t)},n.setNextCallback=function(t){var n=this,a=!0;return this.nextCallback=function(e){a&&(a=!1,n.nextCallback=null,t(e))},this.nextCallback.cancel=function(){a=!1},this.nextCallback},n.onTransitionEnd=function(e,t,n){this.setNextCallback(n);n=null==t&&!this.props.addEndListener;!e||n?setTimeout(this.nextCallback,0):(this.props.addEndListener&&this.props.addEndListener(e,this.nextCallback),null!=t&&setTimeout(this.nextCallback,t))},n.render=function(){var e,t,n=this.state.status;return n===l?null:(e=(t=this.props).children,delete(t=function(e,t){if(null==e)return{};for(var n,a={},r=Object.keys(e),o=0;o 16.8.0"),null)},e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var L=l(n(3)),a=l(n(4)),r=l(n(7)),o=l(n(8)),p=n(0),O=l(p),i=l(n(5)),D=l(n(18)),h=l(n(26)),N=n(11),s=l(n(374)),P=l(n(375));function l(e){return e&&e.__esModule?e:{default:e}}function m(e){e.preventDefault()}u=s.default,(0,o.default)(j,u),j.prototype.getValueLength=function(e){var e=""+e,t=this.props.getValueLength(e);return t="number"!=typeof t?e.length:t},j.prototype.renderControl=function(){var e=this,t=this.props,n=t.hasClear,a=t.readOnly,r=t.state,o=t.prefix,i=t.hint,s=t.extra,l=t.locale,u=t.disabled,t=t.hoverShowClear,c=this.renderLength(),d=null,f=("success"===r?d=O.default.createElement(h.default,{type:"success-filling",className:o+"input-success-icon"}):"loading"===r?d=O.default.createElement(h.default,{type:"loading",className:o+"input-loading-icon"}):"warning"===r&&(d=O.default.createElement(h.default,{type:"warning",className:o+"input-warning-icon"})),null),a=n&&!a&&!!(""+this.state.value)&&!u;return(i||a)&&(u=null,u=i?"string"==typeof i?O.default.createElement(h.default,{type:i,className:o+"input-hint"}):(0,p.isValidElement)(i)?(0,p.cloneElement)(i,{className:(0,D.default)(i.props.className,o+"input-hint")}):i:(t=(0,D.default)(((a={})[o+"input-hint"]=!0,a[o+"input-clear-icon"]=!0,a[o+"input-hover-show"]=t,a)),O.default.createElement(h.default,{type:"delete-filling",role:"button",tabIndex:"0",className:t,"aria-label":l.clear,onClick:this.onClear.bind(this),onMouseDown:m,onKeyDown:this.handleKeyDownFromClear})),f=O.default.createElement("span",{className:o+"input-hint-wrap"},n&&i?O.default.createElement(h.default,{type:"delete-filling",role:"button",tabIndex:"0",className:o+"input-clear "+o+"input-clear-icon","aria-label":l.clear,onClick:this.onClear.bind(this),onMouseDown:m,onKeyDown:this.handleKeyDownFromClear}):null,u)),(f="loading"===r?null:f)||c||d||s?O.default.createElement("span",{onClick:function(){return e.focus()},className:o+"input-control"},f,c,d,s):null},j.prototype.renderLabel=function(){var e=this.props,t=e.label,n=e.prefix,e=e.id;return t?O.default.createElement("label",{className:n+"input-label",htmlFor:e},t):null},j.prototype.renderInner=function(e,t){return e?O.default.createElement("span",{className:t},e):null},j.prototype.onClear=function(e){this.props.disabled||("value"in this.props||this.setState({value:""}),this.props.onChange("",e,"clear"),this.focus())},j.prototype.render=function(){var e,t=this.props,n=t.size,a=t.htmlType,r=t.htmlSize,o=t.autoComplete,i=t.autoFocus,s=t.disabled,l=t.style,u=t.innerBefore,c=t.innerAfter,d=t.innerBeforeClassName,f=t.innerAfterClassName,p=t.className,h=t.hasBorder,m=t.prefix,g=t.isPreview,y=t.renderPreview,v=t.addonBefore,_=t.addonAfter,b=t.addonTextBefore,w=t.addonTextAfter,M=t.inputRender,k=t.rtl,t=t.composition,S=v||_||b||w,h=(0,D.default)(this.getClass(),((E={})[""+m+n]=!0,E[m+"hidden"]="hidden"===this.props.htmlType,E[m+"noborder"]=!h||"file"===this.props.htmlType,E[m+"input-group-auto-width"]=S,E[m+"disabled"]=s,E[p]=!!p&&!S,E)),E=m+"input-inner",d=(0,D.default)(((x={})[E]=!0,x[m+"before"]=!0,x[d]=d,x)),E=(0,D.default)(((x={})[E]=!0,x[m+"after"]=!0,x[m+"input-inner-text"]="string"==typeof c,x[f]=f,x)),x=(0,D.default)(((f={})[m+"form-preview"]=!0,f[p]=!!p,f)),f=this.getProps(),C=N.obj.pickAttrsWith(this.props,"data-"),T=N.obj.pickOthers((0,L.default)({},C,j.propTypes),this.props);return g?(g=f.value,e=this.props.label,"function"==typeof y?O.default.createElement("div",(0,L.default)({},T,{className:x}),y(g,this.props)):O.default.createElement("div",(0,L.default)({},T,{className:x}),v||b,e,u,g,c,_||w)):(y={},t&&(y.onCompositionStart=this.handleCompositionStart,y.onCompositionEnd=this.handleCompositionEnd),x=O.default.createElement("input",(0,L.default)({},T,f,y,{height:"100%",type:a,size:r,autoFocus:i,autoComplete:o,onKeyDown:this.handleKeyDown,ref:this.saveRef})),e=O.default.createElement("span",(0,L.default)({},C,{dir:k?"rtl":void 0,className:h,style:S?void 0:l}),this.renderLabel(),this.renderInner(u,d),M(x),this.renderInner(c,E),this.renderControl()),t=(0,D.default)(((g={})[m+"input-group-text"]=!0,g[""+m+n]=!!n,g[m+"disabled"]=s,g)),f=(0,D.default)(((T={})[t]=b,T)),a=(0,D.default)(((y={})[t]=w,y)),S?O.default.createElement(P.default,(0,L.default)({},C,{prefix:m,className:p,style:l,disabled:s,addonBefore:v||b,addonBeforeClassName:f,addonAfter:_||w,addonAfterClassName:a}),e):e)},o=n=j,n.displayName="Input",n.getDerivedStateFromProps=s.default.getDerivedStateFromProps,n.propTypes=(0,L.default)({},s.default.propTypes,{label:i.default.node,hasClear:i.default.bool,hasBorder:i.default.bool,state:i.default.oneOf(["error","loading","success","warning"]),onPressEnter:i.default.func,htmlType:i.default.string,htmlSize:i.default.string,hint:i.default.oneOfType([i.default.string,i.default.node]),innerBefore:i.default.node,innerAfter:i.default.node,addonBefore:i.default.node,addonAfter:i.default.node,addonTextBefore:i.default.node,addonTextAfter:i.default.node,autoComplete:i.default.string,autoFocus:i.default.bool,inputRender:i.default.func,extra:i.default.node,innerBeforeClassName:i.default.string,innerAfterClassName:i.default.string,isPreview:i.default.bool,renderPreview:i.default.func,hoverShowClear:i.default.bool}),n.defaultProps=(0,L.default)({},s.default.defaultProps,{autoComplete:"off",hasBorder:!0,isPreview:!1,hoverShowClear:!1,onPressEnter:N.func.noop,inputRender:function(e){return e}});var u,i=o;function j(e){(0,a.default)(this,j);var t=(0,r.default)(this,u.call(this,e)),n=(t.handleKeyDown=function(e){13===e.keyCode&&t.props.onPressEnter(e),t.onKeyDown(e)},t.handleKeyDownFromClear=function(e){13===e.keyCode&&t.onClear(e)},void 0),n="value"in e?e.value:e.defaultValue;return t.state={value:void 0===n?"":n},t}t.default=i,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var a,r=h(n(3)),o=h(n(4)),i=h(n(7)),s=h(n(8)),l=h(n(0)),u=h(n(5)),c=h(n(18)),d=n(31),f=h(n(6)),p=n(11),n=h(n(44));function h(e){return e&&e.__esModule?e:{default:e}}m=l.default.Component,(0,s.default)(g,m),g.getDerivedStateFromProps=function(e,t){return"value"in e&&e.value!==t.value&&!t.composition?{value:null==(t=e.value)?"":t}:null},g.prototype.ieHack=function(e){return e},g.prototype.onChange=function(e){"stopPropagation"in e?e.stopPropagation():"cancelBubble"in e&&e.cancelBubble();var t=e.target.value;this.props.trim&&(t=t.trim()),t=this.ieHack(t),"value"in this.props&&!this.state.composition||this.setState({value:t}),this.state.composition||(t&&"number"===this.props.htmlType&&(t=Number(t)),this.props.onChange(t,e))},g.prototype.onKeyDown=function(e){var t=e.target.value,n=this.props.maxLength,t=0>6]+c[128|63&l]:l<55296||57344<=l?i+=c[224|l>>12]+c[128|l>>6&63]+c[128|63&l]:(s+=1,l=65536+((1023&l)<<10|1023&o.charCodeAt(s)),i+=c[240|l>>18]+c[128|l>>12&63]+c[128|l>>6&63]+c[128|63&l])}return i},isBuffer:function(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},maybeMap:function(e,t){if(m(e)){for(var n=[],a=0;athis.popupNode.offsetWidth&&p(this.popupNode,"width",s.offsetWidth+"px"),"outside"!==a||"hoz"===r&&1===n||(p(this.popupNode,"height",u.offsetHeight+"px"),this.popupNode.firstElementChild&&p(this.popupNode.firstElementChild,"overflow-y","auto")),this.popupProps);c.onOpen&&c.onOpen()}catch(e){return null}},S.prototype.handlePopupClose=function(){var e=this.props.root.popupNodes,t=e.indexOf(this.popupNode),e=(-1t?r[t+1]:r[0])}),n[a]||(o=r[0]),i.onSort(a,o)},i.keydownHandler=function(e){e.preventDefault(),e.stopPropagation(),e.keyCode===s.KEYCODE.ENTER&&i.handleClick()},i.onSort=function(e,t){var n={};i.props.onSort(e,n[e]=t,n)},(0,o.default)(i,e)}i.displayName="Sort",t.default=i,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r=d(n(3)),a=d(n(4)),o=d(n(7)),i=d(n(8)),s=d(n(0)),l=d(n(5)),u=d(n(18)),c=d(n(405));function d(e){return e&&e.__esModule?e:{default:e}}f=s.default.Component,(0,i.default)(p,f),p.prototype.render=function(){var e=this.props,t=e.className,n=e.record,e=e.primaryKey,a=this.context.selectedRowKeys,n=(0,u.default)(((a={selected:-1t.highWaterMark&&(t.highWaterMark=(p<=(n=e)?n=p:(n--,n=(n=(n=(n=(n|=n>>>1)|n>>>2)|n>>>4)|n>>>8)|n>>>16,n++),n)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function b(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(_("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?y.nextTick(w,e):w(e))}function w(e){_("emit readable"),e.emit("readable"),x(e)}function M(e,t){t.readingMore||(t.readingMore=!0,y.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var a;eo.length?o.length:e;if(i===o.length?r+=o:r+=o.slice(0,e),0===(e-=i)){i===o.length?(++a,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n).data=o.slice(i);break}++a}return t.length-=a,r}:function(e,t){var n=c.allocUnsafe(e),a=t.head,r=1;a.data.copy(n),e-=a.data.length;for(;a=a.next;){var o=a.data,i=e>o.length?o.length:e;if(o.copy(n,n.length-e,0,i),0===(e-=i)){i===o.length?(++r,a.next?t.head=a.next:t.head=t.tail=null):(t.head=a).data=o.slice(i);break}++r}return t.length-=r,n})(e,t);return a}(e,t.buffer,t.decoder),n)}function T(e){var t=e._readableState;if(0=n.highWaterMark||n.ended)?(_("read: emitReadable",n.length,n.ended),(0===n.length&&n.ended?T:b)(this),null):0===(e=h(e,n))&&n.ended?(0===n.length&&T(this),null):(t=n.needReadable,_("need readable",t),(0===n.length||n.length-e=11?e:e+12;else if(t==="下午"||t==="晚上")return e+12},meridiem:function(e,t,n){var a=e*100+t;if(a<600)return"凌晨";else if(a<900)return"早上";else if(a<1130)return"上午";else if(a<1230)return"中午";else if(a<1800)return"下午";else return"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,t){switch(t){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s後",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})}(n(9))},function(e,t,n){"use strict";t.__esModule=!0;var u=p(n(3)),a=p(n(4)),r=p(n(7)),o=p(n(8)),i=n(0),c=p(i),s=p(n(5)),d=p(n(19)),l=p(n(6)),f=n(11);function p(e){return e&&e.__esModule?e:{default:e}}h=i.Component,(0,o.default)(m,h),m.prototype.render=function(){var e,t=this.props,n=t.prefix,a=t.type,r=t.size,o=t.className,i=t.rtl,s=t.style,t=t.children,l=f.obj.pickOthers((0,u.default)({},m.propTypes),this.props),n=(0,d.default)(((e={})[n+"icon"]=!0,e[n+"icon-"+a]=!!a,e[""+n+r]=!!r&&"string"==typeof r,e[o]=!!o,e)),o=(i&&-1!==["arrow-left","arrow-right","arrow-double-left","arrow-double-right","switch","sorting","descending","ascending"].indexOf(a)&&(l.dir="rtl"),"number"==typeof r?{width:r,height:r,lineHeight:r+"px",fontSize:r}:{});return c.default.createElement("i",(0,u.default)({},l,{style:(0,u.default)({},o,s),className:n}),t)},i=n=m,n.propTypes=(0,u.default)({},l.default.propTypes,{type:s.default.string,children:s.default.node,size:s.default.oneOfType([s.default.oneOf(["xxs","xs","small","medium","large","xl","xxl","xxxl","inherit"]),s.default.number]),className:s.default.string,style:s.default.object}),n.defaultProps={prefix:"next-",size:"medium"},n._typeMark="icon";var h,o=i;function m(){return(0,a.default)(this,m),(0,r.default)(this,h.apply(this,arguments))}o.displayName="Icon",t.default=o,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var g=l(n(3)),y=l(n(17)),a=l(n(42)),r=l(n(4)),o=l(n(7)),i=l(n(8)),v=n(0),_=l(v),s=l(n(5)),b=n(166),w=l(n(544));function l(e){return e&&e.__esModule?e:{default:e}}function u(){}function M(e){return _.default.Children.toArray(e.children)[0]||null}c=v.Component,(0,i.default)(d,c),d.prototype.normalizeNames=function(e){return"string"==typeof e?{appear:e+"-appear",appearActive:e+"-appear-active",enter:e+"-enter",enterActive:e+"-enter-active",leave:e+"-leave",leaveActive:e+"-leave-active"}:"object"===(void 0===e?"undefined":(0,a.default)(e))?{appear:e.appear,appearActive:e.appear+"-active",enter:""+e.enter,enterActive:e.enter+"-active",leave:""+e.leave,leaveActive:e.leave+"-active"}:void 0},d.prototype.render=function(){var t=this,e=this.props,n=e.animation,a=e.children,r=e.animationAppear,o=e.singleMode,i=e.component,s=e.beforeAppear,l=e.onAppear,u=e.afterAppear,c=e.beforeEnter,d=e.onEnter,f=e.afterEnter,p=e.beforeLeave,h=e.onLeave,m=e.afterLeave,e=(0,y.default)(e,["animation","children","animationAppear","singleMode","component","beforeAppear","onAppear","afterAppear","beforeEnter","onEnter","afterEnter","beforeLeave","onLeave","afterLeave"]),a=v.Children.map(a,function(e){return _.default.createElement(w.default,{key:e.key,names:t.normalizeNames(n),onAppear:s,onAppearing:l,onAppeared:u,onEnter:c,onEntering:d,onEntered:f,onExit:p,onExiting:h,onExited:m},e)});return _.default.createElement(b.TransitionGroup,(0,g.default)({appear:r,component:o?M:i},e),a)},i=n=d,n.propTypes={animation:s.default.oneOfType([s.default.string,s.default.object]),animationAppear:s.default.bool,component:s.default.any,singleMode:s.default.bool,children:s.default.oneOfType([s.default.element,s.default.arrayOf(s.default.element)]),beforeAppear:s.default.func,onAppear:s.default.func,afterAppear:s.default.func,beforeEnter:s.default.func,onEnter:s.default.func,afterEnter:s.default.func,beforeLeave:s.default.func,onLeave:s.default.func,afterLeave:s.default.func},n.defaultProps={animationAppear:!0,component:"div",singleMode:!0,beforeAppear:u,onAppear:u,afterAppear:u,beforeEnter:u,onEnter:u,afterEnter:u,beforeLeave:u,onLeave:u,afterLeave:u};var c,s=i;function d(){return(0,r.default)(this,d),(0,o.default)(this,c.apply(this,arguments))}s.displayName="Animate",t.default=s,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.default=t.EXITING=t.ENTERED=t.ENTERING=t.EXITED=t.UNMOUNTED=void 0;var a=function(e){{if(e&&e.__esModule)return e;var t,n={};if(null!=e)for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&((t=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,a):{}).get||t.set?Object.defineProperty(n,a,t):n[a]=e[a]);return n.default=e,n}}(n(5)),o=s(n(0)),i=s(n(25)),r=n(31);n(360);function s(e){return e&&e.__esModule?e:{default:e}}var l="unmounted",u=(t.UNMOUNTED=l,"exited"),c=(t.EXITED=u,"entering"),d=(t.ENTERING=c,"entered"),f=(t.ENTERED=d,"exiting"),n=(t.EXITING=f,function(r){var e;function t(e,t){var n,a=r.call(this,e,t)||this,t=t.transitionGroup,t=t&&!t.isMounting?e.enter:e.appear;return a.appearStatus=null,e.in?t?(n=u,a.appearStatus=c):n=d:n=e.unmountOnExit||e.mountOnEnter?l:u,a.state={status:n},a.nextCallback=null,a}e=r,(n=t).prototype=Object.create(e.prototype),(n.prototype.constructor=n).__proto__=e;var n=t.prototype;return n.getChildContext=function(){return{transitionGroup:null}},t.getDerivedStateFromProps=function(e,t){return e.in&&t.status===l?{status:u}:null},n.componentDidMount=function(){this.updateStatus(!0,this.appearStatus)},n.componentDidUpdate=function(e){var t=null;e!==this.props&&(e=this.state.status,this.props.in?e!==c&&e!==d&&(t=c):e!==c&&e!==d||(t=f)),this.updateStatus(!1,t)},n.componentWillUnmount=function(){this.cancelNextCallback()},n.getTimeouts=function(){var e,t,n=this.props.timeout,a=e=t=n;return null!=n&&"number"!=typeof n&&(a=n.exit,e=n.enter,t=void 0!==n.appear?n.appear:e),{exit:a,enter:e,appear:t}},n.updateStatus=function(e,t){var n;void 0===e&&(e=!1),null!==t?(this.cancelNextCallback(),n=i.default.findDOMNode(this),t===c?this.performEnter(n,e):this.performExit(n)):this.props.unmountOnExit&&this.state.status===u&&this.setState({status:l})},n.performEnter=function(e,t){var n=this,a=this.props.enter,r=this.context.transitionGroup?this.context.transitionGroup.isMounting:t,o=this.getTimeouts(),i=r?o.appear:o.enter;t||a?(this.props.onEnter(e,r),this.safeSetState({status:c},function(){n.props.onEntering(e,r),n.onTransitionEnd(e,i,function(){n.safeSetState({status:d},function(){n.props.onEntered(e,r)})})})):this.safeSetState({status:d},function(){n.props.onEntered(e)})},n.performExit=function(e){var t=this,n=this.props.exit,a=this.getTimeouts();n?(this.props.onExit(e),this.safeSetState({status:f},function(){t.props.onExiting(e),t.onTransitionEnd(e,a.exit,function(){t.safeSetState({status:u},function(){t.props.onExited(e)})})})):this.safeSetState({status:u},function(){t.props.onExited(e)})},n.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},n.safeSetState=function(e,t){t=this.setNextCallback(t),this.setState(e,t)},n.setNextCallback=function(t){var n=this,a=!0;return this.nextCallback=function(e){a&&(a=!1,n.nextCallback=null,t(e))},this.nextCallback.cancel=function(){a=!1},this.nextCallback},n.onTransitionEnd=function(e,t,n){this.setNextCallback(n);n=null==t&&!this.props.addEndListener;!e||n?setTimeout(this.nextCallback,0):(this.props.addEndListener&&this.props.addEndListener(e,this.nextCallback),null!=t&&setTimeout(this.nextCallback,t))},n.render=function(){var e,t,n=this.state.status;return n===l?null:(e=(t=this.props).children,delete(t=function(e,t){if(null==e)return{};for(var n,a={},r=Object.keys(e),o=0;o 16.8.0"),null)},e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var L=l(n(3)),a=l(n(4)),r=l(n(7)),o=l(n(8)),p=n(0),O=l(p),i=l(n(5)),D=l(n(19)),h=l(n(26)),N=n(11),s=l(n(374)),P=l(n(375));function l(e){return e&&e.__esModule?e:{default:e}}function m(e){e.preventDefault()}u=s.default,(0,o.default)(j,u),j.prototype.getValueLength=function(e){var e=""+e,t=this.props.getValueLength(e);return t="number"!=typeof t?e.length:t},j.prototype.renderControl=function(){var e=this,t=this.props,n=t.hasClear,a=t.readOnly,r=t.state,o=t.prefix,i=t.hint,s=t.extra,l=t.locale,u=t.disabled,t=t.hoverShowClear,c=this.renderLength(),d=null,f=("success"===r?d=O.default.createElement(h.default,{type:"success-filling",className:o+"input-success-icon"}):"loading"===r?d=O.default.createElement(h.default,{type:"loading",className:o+"input-loading-icon"}):"warning"===r&&(d=O.default.createElement(h.default,{type:"warning",className:o+"input-warning-icon"})),null),a=n&&!a&&!!(""+this.state.value)&&!u;return(i||a)&&(u=null,u=i?"string"==typeof i?O.default.createElement(h.default,{type:i,className:o+"input-hint"}):(0,p.isValidElement)(i)?(0,p.cloneElement)(i,{className:(0,D.default)(i.props.className,o+"input-hint")}):i:(t=(0,D.default)(((a={})[o+"input-hint"]=!0,a[o+"input-clear-icon"]=!0,a[o+"input-hover-show"]=t,a)),O.default.createElement(h.default,{type:"delete-filling",role:"button",tabIndex:"0",className:t,"aria-label":l.clear,onClick:this.onClear.bind(this),onMouseDown:m,onKeyDown:this.handleKeyDownFromClear})),f=O.default.createElement("span",{className:o+"input-hint-wrap"},n&&i?O.default.createElement(h.default,{type:"delete-filling",role:"button",tabIndex:"0",className:o+"input-clear "+o+"input-clear-icon","aria-label":l.clear,onClick:this.onClear.bind(this),onMouseDown:m,onKeyDown:this.handleKeyDownFromClear}):null,u)),(f="loading"===r?null:f)||c||d||s?O.default.createElement("span",{onClick:function(){return e.focus()},className:o+"input-control"},f,c,d,s):null},j.prototype.renderLabel=function(){var e=this.props,t=e.label,n=e.prefix,e=e.id;return t?O.default.createElement("label",{className:n+"input-label",htmlFor:e},t):null},j.prototype.renderInner=function(e,t){return e?O.default.createElement("span",{className:t},e):null},j.prototype.onClear=function(e){this.props.disabled||("value"in this.props||this.setState({value:""}),this.props.onChange("",e,"clear"),this.focus())},j.prototype.render=function(){var e,t=this.props,n=t.size,a=t.htmlType,r=t.htmlSize,o=t.autoComplete,i=t.autoFocus,s=t.disabled,l=t.style,u=t.innerBefore,c=t.innerAfter,d=t.innerBeforeClassName,f=t.innerAfterClassName,p=t.className,h=t.hasBorder,m=t.prefix,g=t.isPreview,y=t.renderPreview,v=t.addonBefore,_=t.addonAfter,b=t.addonTextBefore,w=t.addonTextAfter,M=t.inputRender,k=t.rtl,t=t.composition,S=v||_||b||w,h=(0,D.default)(this.getClass(),((E={})[""+m+n]=!0,E[m+"hidden"]="hidden"===this.props.htmlType,E[m+"noborder"]=!h||"file"===this.props.htmlType,E[m+"input-group-auto-width"]=S,E[m+"disabled"]=s,E[p]=!!p&&!S,E)),E=m+"input-inner",d=(0,D.default)(((x={})[E]=!0,x[m+"before"]=!0,x[d]=d,x)),E=(0,D.default)(((x={})[E]=!0,x[m+"after"]=!0,x[m+"input-inner-text"]="string"==typeof c,x[f]=f,x)),x=(0,D.default)(((f={})[m+"form-preview"]=!0,f[p]=!!p,f)),f=this.getProps(),C=N.obj.pickAttrsWith(this.props,"data-"),T=N.obj.pickOthers((0,L.default)({},C,j.propTypes),this.props);return g?(g=f.value,e=this.props.label,"function"==typeof y?O.default.createElement("div",(0,L.default)({},T,{className:x}),y(g,this.props)):O.default.createElement("div",(0,L.default)({},T,{className:x}),v||b,e,u,g,c,_||w)):(y={},t&&(y.onCompositionStart=this.handleCompositionStart,y.onCompositionEnd=this.handleCompositionEnd),x=O.default.createElement("input",(0,L.default)({},T,f,y,{height:"100%",type:a,size:r,autoFocus:i,autoComplete:o,onKeyDown:this.handleKeyDown,ref:this.saveRef})),e=O.default.createElement("span",(0,L.default)({},C,{dir:k?"rtl":void 0,className:h,style:S?void 0:l}),this.renderLabel(),this.renderInner(u,d),M(x),this.renderInner(c,E),this.renderControl()),t=(0,D.default)(((g={})[m+"input-group-text"]=!0,g[""+m+n]=!!n,g[m+"disabled"]=s,g)),f=(0,D.default)(((T={})[t]=b,T)),a=(0,D.default)(((y={})[t]=w,y)),S?O.default.createElement(P.default,(0,L.default)({},C,{prefix:m,className:p,style:l,disabled:s,addonBefore:v||b,addonBeforeClassName:f,addonAfter:_||w,addonAfterClassName:a}),e):e)},o=n=j,n.displayName="Input",n.getDerivedStateFromProps=s.default.getDerivedStateFromProps,n.propTypes=(0,L.default)({},s.default.propTypes,{label:i.default.node,hasClear:i.default.bool,hasBorder:i.default.bool,state:i.default.oneOf(["error","loading","success","warning"]),onPressEnter:i.default.func,htmlType:i.default.string,htmlSize:i.default.string,hint:i.default.oneOfType([i.default.string,i.default.node]),innerBefore:i.default.node,innerAfter:i.default.node,addonBefore:i.default.node,addonAfter:i.default.node,addonTextBefore:i.default.node,addonTextAfter:i.default.node,autoComplete:i.default.string,autoFocus:i.default.bool,inputRender:i.default.func,extra:i.default.node,innerBeforeClassName:i.default.string,innerAfterClassName:i.default.string,isPreview:i.default.bool,renderPreview:i.default.func,hoverShowClear:i.default.bool}),n.defaultProps=(0,L.default)({},s.default.defaultProps,{autoComplete:"off",hasBorder:!0,isPreview:!1,hoverShowClear:!1,onPressEnter:N.func.noop,inputRender:function(e){return e}});var u,i=o;function j(e){(0,a.default)(this,j);var t=(0,r.default)(this,u.call(this,e)),n=(t.handleKeyDown=function(e){13===e.keyCode&&t.props.onPressEnter(e),t.onKeyDown(e)},t.handleKeyDownFromClear=function(e){13===e.keyCode&&t.onClear(e)},void 0),n="value"in e?e.value:e.defaultValue;return t.state={value:void 0===n?"":n},t}t.default=i,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var a,r=h(n(3)),o=h(n(4)),i=h(n(7)),s=h(n(8)),l=h(n(0)),u=h(n(5)),c=h(n(19)),d=n(31),f=h(n(6)),p=n(11),n=h(n(44));function h(e){return e&&e.__esModule?e:{default:e}}m=l.default.Component,(0,s.default)(g,m),g.getDerivedStateFromProps=function(e,t){return"value"in e&&e.value!==t.value&&!t.composition?{value:null==(t=e.value)?"":t}:null},g.prototype.ieHack=function(e){return e},g.prototype.onChange=function(e){"stopPropagation"in e?e.stopPropagation():"cancelBubble"in e&&e.cancelBubble();var t=e.target.value;this.props.trim&&(t=t.trim()),t=this.ieHack(t),"value"in this.props&&!this.state.composition||this.setState({value:t}),this.state.composition||(t&&"number"===this.props.htmlType&&(t=Number(t)),this.props.onChange(t,e))},g.prototype.onKeyDown=function(e){var t=e.target.value,n=this.props.maxLength,t=0>6]+c[128|63&l]:l<55296||57344<=l?i+=c[224|l>>12]+c[128|l>>6&63]+c[128|63&l]:(s+=1,l=65536+((1023&l)<<10|1023&o.charCodeAt(s)),i+=c[240|l>>18]+c[128|l>>12&63]+c[128|l>>6&63]+c[128|63&l])}return i},isBuffer:function(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},maybeMap:function(e,t){if(m(e)){for(var n=[],a=0;athis.popupNode.offsetWidth&&p(this.popupNode,"width",s.offsetWidth+"px"),"outside"!==a||"hoz"===r&&1===n||(p(this.popupNode,"height",u.offsetHeight+"px"),this.popupNode.firstElementChild&&p(this.popupNode.firstElementChild,"overflow-y","auto")),this.popupProps);c.onOpen&&c.onOpen()}catch(e){return null}},S.prototype.handlePopupClose=function(){var e=this.props.root.popupNodes,t=e.indexOf(this.popupNode),e=(-1t?r[t+1]:r[0])}),n[a]||(o=r[0]),i.onSort(a,o)},i.keydownHandler=function(e){e.preventDefault(),e.stopPropagation(),e.keyCode===s.KEYCODE.ENTER&&i.handleClick()},i.onSort=function(e,t){var n={};i.props.onSort(e,n[e]=t,n)},(0,o.default)(i,e)}i.displayName="Sort",t.default=i,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var r=d(n(3)),a=d(n(4)),o=d(n(7)),i=d(n(8)),s=d(n(0)),l=d(n(5)),u=d(n(19)),c=d(n(405));function d(e){return e&&e.__esModule?e:{default:e}}f=s.default.Component,(0,i.default)(p,f),p.prototype.render=function(){var e=this.props,t=e.className,n=e.record,e=e.primaryKey,a=this.context.selectedRowKeys,n=(0,u.default)(((a={selected:-1t.highWaterMark&&(t.highWaterMark=(p<=(n=e)?n=p:(n--,n=(n=(n=(n=(n|=n>>>1)|n>>>2)|n>>>4)|n>>>8)|n>>>16,n++),n)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function b(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(_("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?y.nextTick(w,e):w(e))}function w(e){_("emit readable"),e.emit("readable"),x(e)}function M(e,t){t.readingMore||(t.readingMore=!0,y.nextTick(k,e,t))}function k(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var a;eo.length?o.length:e;if(i===o.length?r+=o:r+=o.slice(0,e),0===(e-=i)){i===o.length?(++a,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n).data=o.slice(i);break}++a}return t.length-=a,r}:function(e,t){var n=c.allocUnsafe(e),a=t.head,r=1;a.data.copy(n),e-=a.data.length;for(;a=a.next;){var o=a.data,i=e>o.length?o.length:e;if(o.copy(n,n.length-e,0,i),0===(e-=i)){i===o.length?(++r,a.next?t.head=a.next:t.head=t.tail=null):(t.head=a).data=o.slice(i);break}++r}return t.length-=r,n})(e,t);return a}(e,t.buffer,t.decoder),n)}function T(e){var t=e._readableState;if(0=n.highWaterMark||n.ended)?(_("read: emitReadable",n.length,n.ended),(0===n.length&&n.ended?T:b)(this),null):0===(e=h(e,n))&&n.ended?(0===n.length&&T(this),null):(t=n.needReadable,_("need readable",t),(0===n.length||n.length-e * @license MIT */ -var S=P(706),o=P(707),s=P(708);function n(){return d.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function l(e,t){if(n()=n())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+n().toString(16)+" bytes");return 0|e}function f(e,t){if(d.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;var n=(e="string"!=typeof e?""+e:e).length;if(0===n)return 0;for(var a=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return L(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return O(e).length;default:if(a)return L(e).length;t=(""+t).toLowerCase(),a=!0}}function t(e,t,n){var a,r=!1;if((t=void 0===t||t<0?0:t)>this.length)return"";if((n=void 0===n||n>this.length?this.length:n)<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e=e||"utf8";;)switch(e){case"hex":var o=this,i=t,s=n,l=o.length;(!s||s<0||l=e.length){if(r)return-1;n=e.length-1}else if(n<0){if(!r)return-1;n=0}if("string"==typeof t&&(t=d.from(t,a)),d.isBuffer(t))return 0===t.length?-1:m(e,t,n,a,r);if("number"==typeof t)return t&=255,d.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?(r?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(e,t,n):m(e,[t],n,a,r);throw new TypeError("val must be string, number or Buffer")}function m(e,t,n,a,r){var o=1,i=e.length,s=t.length;if(void 0!==a&&("ucs2"===(a=String(a).toLowerCase())||"ucs-2"===a||"utf16le"===a||"utf-16le"===a)){if(e.length<2||t.length<2)return-1;i/=o=2,s/=2,n/=2}function l(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(r)for(var u=-1,c=n;c>8,r.push(n%256),r.push(a);return r}(t,e.length-n),e,n,a)}function E(e,t,n){n=Math.min(e.length,n);for(var a=[],r=t;r>>10&1023|55296),c=56320|1023&c),a.push(c),r+=d}var f=a,p=f.length;if(p<=v)return String.fromCharCode.apply(String,f);for(var h="",m=0;mt)&&(e+=" ... "),""},d.prototype.compare=function(e,t,n,a,r){if(!d.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===n&&(n=e?e.length:0),void 0===a&&(a=0),void 0===r&&(r=this.length),(t=void 0===t?0:t)<0||n>e.length||a<0||r>this.length)throw new RangeError("out of range index");if(r<=a&&n<=t)return 0;if(r<=a)return-1;if(n<=t)return 1;if(this===e)return 0;for(var o=(r>>>=0)-(a>>>=0),i=(n>>>=0)-(t>>>=0),s=Math.min(o,i),l=this.slice(a,r),u=e.slice(t,n),c=0;cthis.length)throw new RangeError("Attempt to write outside buffer bounds");a=a||"utf8";for(var o,i,s,l=!1;;)switch(a){case"hex":var u=this,c=e,d=t,f=n,p=(d=Number(d)||0,u.length-d);if((!f||p<(f=Number(f)))&&(f=p),(p=c.length)%2!=0)throw new TypeError("Invalid hex string");p/2e.length)throw new RangeError("Index out of range")}function w(e,t,n,a){t<0&&(t=65535+t+1);for(var r=0,o=Math.min(e.length-n,2);r>>8*(a?r:1-r)}function M(e,t,n,a){t<0&&(t=4294967295+t+1);for(var r=0,o=Math.min(e.length-n,4);r>>8*(a?r:3-r)&255}function k(e,t,n,a){if(n+a>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function x(e,t,n,a,r){return r||k(e,0,n,4),o.write(e,t,n,a,23,4),n+4}function C(e,t,n,a,r){return r||k(e,0,n,8),o.write(e,t,n,a,52,8),n+8}d.prototype.slice=function(e,t){var n=this.length;if((e=~~e)<0?(e+=n)<0&&(e=0):n>>8):w(this,e,t,!0),t+2},d.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,2,65535,0),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):w(this,e,t,!1),t+2},d.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,4294967295,0),d.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},d.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,4294967295,0),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},d.prototype.writeIntLE=function(e,t,n,a){e=+e,t|=0,a||b(this,e,t,n,(a=Math.pow(2,8*n-1))-1,-a);var r=0,o=1,i=0;for(this[t]=255&e;++r>0)-i&255;return t+n},d.prototype.writeIntBE=function(e,t,n,a){e=+e,t|=0,a||b(this,e,t,n,(a=Math.pow(2,8*n-1))-1,-a);var r=n-1,o=1,i=0;for(this[t+r]=255&e;0<=--r&&(o*=256);)e<0&&0===i&&0!==this[t+r+1]&&(i=1),this[t+r]=(e/o>>0)-i&255;return t+n},d.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,1,127,-128),d.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&(e=e<0?255+e+1:e),t+1},d.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,2,32767,-32768),d.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):w(this,e,t,!0),t+2},d.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,2,32767,-32768),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):w(this,e,t,!1),t+2},d.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,2147483647,-2147483648),d.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},d.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},d.prototype.writeFloatLE=function(e,t,n){return x(this,e,t,!0,n)},d.prototype.writeFloatBE=function(e,t,n){return x(this,e,t,!1,n)},d.prototype.writeDoubleLE=function(e,t,n){return C(this,e,t,!0,n)},d.prototype.writeDoubleBE=function(e,t,n){return C(this,e,t,!1,n)},d.prototype.copy=function(e,t,n,a){if(n=n||0,a||0===a||(a=this.length),t>=e.length&&(t=e.length),(a=0=this.length)throw new RangeError("sourceStart out of bounds");if(a<0)throw new RangeError("sourceEnd out of bounds");a>this.length&&(a=this.length);var r,o=(a=e.length-t>>=0,n=void 0===n?this.length:n>>>0,"number"==typeof(e=e||0))for(s=t;s>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function O(e){return S.toByteArray(function(e){var t;if((e=((t=e).trim?t.trim():t.replace(/^\s+|\s+$/g,"")).replace(T,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function D(e,t,n,a){for(var r=0;r=t.length||r>=e.length);++r)t[r+n]=e[r];return r}}.call(this,P(65))},function(e,t,n){"use strict";var o=n(138);function i(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,a=this._readableState&&this._readableState.destroyed,r=this._writableState&&this._writableState.destroyed;return a||r?t?t(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,o.nextTick(i,this,e)):o.nextTick(i,this,e)):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?n._writableState?n._writableState.errorEmitted||(n._writableState.errorEmitted=!0,o.nextTick(i,n,e)):o.nextTick(i,n,e):t&&t(e)})),this},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var a=n(139).Buffer,r=a.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function o(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"==typeof t||a.isEncoding!==r&&r(e))return t||e;throw new Error("Unknown encoding: "+e)}function i(e){var t;switch(this.encoding=o(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=l,t=4;break;case"base64":this.text=d,this.end=f,t=3;break;default:return this.write=p,void(this.end=h)}this.lastNeed=0,this.lastTotal=0,this.lastChar=a.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function l(e){var t,n=this.lastTotal-this.lastNeed,a=(t=this,128!=(192&(a=e)[0])?(t.lastNeed=0,"�"):1e.slidesToShow&&(n=e.slideWidth*e.slidesToShow*-1,o=e.slideHeight*e.slidesToShow*-1),e.slideCount%e.slidesToScroll!=0&&(t=e.slideIndex+e.slidesToScroll>e.slideCount&&e.slideCount>e.slidesToShow,t=e.rtl?(e.slideIndex>=e.slideCount?e.slideCount-e.slideIndex:e.slideIndex)+e.slidesToScroll>e.slideCount&&e.slideCount>e.slidesToShow:t)&&(o=e.slideIndex>e.slideCount?(n=(e.slidesToShow-(e.slideIndex-e.slideCount))*e.slideWidth*-1,(e.slidesToShow-(e.slideIndex-e.slideCount))*e.slideHeight*-1):(n=e.slideCount%e.slidesToScroll*e.slideWidth*-1,e.slideCount%e.slidesToScroll*e.slideHeight*-1))):e.slideCount%e.slidesToScroll!=0&&e.slideIndex+e.slidesToScroll>e.slideCount&&e.slideCount>e.slidesToShow&&(n=(e.slidesToShow-e.slideCount%e.slidesToScroll)*e.slideWidth),e.centerMode&&(e.infinite?n+=e.slideWidth*Math.floor(e.slidesToShow/2):n=e.slideWidth*Math.floor(e.slidesToShow/2)),a=e.vertical?e.slideIndex*e.slideHeight*-1+o:e.slideIndex*e.slideWidth*-1+n,!0===e.variableWidth&&(t=void 0,a=(r=e.slideCount<=e.slidesToShow||!1===e.infinite?i.default.findDOMNode(e.trackRef).childNodes[e.slideIndex]:(t=e.slideIndex+e.slidesToShow,i.default.findDOMNode(e.trackRef).childNodes[t]))?-1*r.offsetLeft:0,!0===e.centerMode)&&(r=!1===e.infinite?i.default.findDOMNode(e.trackRef).children[e.slideIndex]:i.default.findDOMNode(e.trackRef).children[e.slideIndex+e.slidesToShow+1])?-1*r.offsetLeft+(e.listWidth-r.offsetWidth)/2:a)}},function(e,t,n){"use strict";t.__esModule=!0;var p=u(n(3)),h=u(n(16)),o=u(n(4)),i=u(n(7)),a=u(n(8)),m=u(n(0)),r=u(n(5)),g=u(n(18)),s=u(n(6)),y=u(n(26)),l=n(11);function u(e){return e&&e.__esModule?e:{default:e}}c=m.default.Component,(0,a.default)(d,c),d.prototype.render=function(){var e=this.props,t=e.title,n=e.children,a=e.className,r=e.isExpanded,o=e.disabled,i=e.style,s=e.prefix,l=e.onClick,u=e.id,e=(0,h.default)(e,["title","children","className","isExpanded","disabled","style","prefix","onClick","id"]),a=(0,g.default)(((c={})[s+"collapse-panel"]=!0,c[s+"collapse-panel-hidden"]=!r,c[s+"collapse-panel-expanded"]=r,c[s+"collapse-panel-disabled"]=o,c[a]=a,c)),c=(0,g.default)(((c={})[s+"collapse-panel-icon"]=!0,c[s+"collapse-panel-icon-expanded"]=r,c)),d=u?u+"-heading":void 0,f=u?u+"-region":void 0;return m.default.createElement("div",(0,p.default)({className:a,style:i,id:u},e),m.default.createElement("div",{id:d,className:s+"collapse-panel-title",onClick:l,onKeyDown:this.onKeyDown,tabIndex:"0","aria-disabled":o,"aria-expanded":r,"aria-controls":f,role:"button"},m.default.createElement(y.default,{type:"arrow-right",className:c,"aria-hidden":"true"}),t),m.default.createElement("div",{className:s+"collapse-panel-content",role:"region",id:f},n))},a=n=d,n.propTypes={prefix:r.default.string,style:r.default.object,children:r.default.any,isExpanded:r.default.bool,disabled:r.default.bool,title:r.default.node,className:r.default.string,onClick:r.default.func,id:r.default.string},n.defaultProps={prefix:"next-",isExpanded:!1,onClick:l.func.noop},n.isNextPanel=!0;var c,r=a;function d(){var e,n;(0,o.default)(this,d);for(var t=arguments.length,a=Array(t),r=0;r\n com.alibaba.nacos\n nacos-client\n ${version}\n \n*/\npackage com.alibaba.nacos.example;\n\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * Config service example\n *\n * @author Nacos\n *\n */\npublic class ConfigExample {\n\n\tpublic static void main(String[] args) throws NacosException, InterruptedException {\n\t\tString serverAddr = "localhost";\n\t\tString dataId = "'.concat(e.dataId,'";\n\t\tString group = "').concat(e.group,'";\n\t\tProperties properties = new Properties();\n\t\tproperties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);\n\t\tConfigService configService = NacosFactory.createConfigService(properties);\n\t\tString content = configService.getConfig(dataId, group, 5000);\n\t\tSystem.out.println(content);\n\t\tconfigService.addListener(dataId, group, new Listener() {\n\t\t\t@Override\n\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\tSystem.out.println("receive:" + configInfo);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic Executor getExecutor() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t});\n\n\t\tboolean isPublishOk = configService.publishConfig(dataId, group, "content");\n\t\tSystem.out.println(isPublishOk);\n\n\t\tThread.sleep(3000);\n\t\tcontent = configService.getConfig(dataId, group, 5000);\n\t\tSystem.out.println(content);\n\n\t\tboolean isRemoveOk = configService.removeConfig(dataId, group);\n\t\tSystem.out.println(isRemoveOk);\n\t\tThread.sleep(3000);\n\n\t\tcontent = configService.getConfig(dataId, group, 5000);\n\t\tSystem.out.println(content);\n\t\tThread.sleep(300000);\n\n\t}\n}\n')}},{key:"getNodejsCode",value:function(e){return"TODO"}},{key:"getCppCode",value:function(e){return"TODO"}},{key:"getShellCode",value:function(e){return"TODO"}},{key:"getPythonCode",value:function(e){return'/*\n* Demo for Nacos\n*/\nimport json\nimport socket\n\nimport nacos\n\n\ndef get_host_ip():\n res = socket.gethostbyname(socket.gethostname())\n return res\n\n\ndef load_config(content):\n _config = json.loads(content)\n return _config\n\n\ndef nacos_config_callback(args):\n content = args[\'raw_content\']\n load_config(content)\n\n\nclass NacosClient:\n service_name = None\n service_port = None\n service_group = None\n\n def __init__(self, server_endpoint, namespace_id, username=None, password=None):\n self.client = nacos.NacosClient(server_endpoint,\n namespace=namespace_id,\n username=username,\n password=password)\n self.endpoint = server_endpoint\n self.service_ip = get_host_ip()\n\n def register(self):\n self.client.add_naming_instance(self.service_name,\n self.service_ip,\n self.service_port,\n group_name=self.service_group)\n\n def modify(self, service_name, service_ip=None, service_port=None):\n self.client.modify_naming_instance(service_name,\n service_ip if service_ip else self.service_ip,\n service_port if service_port else self.service_port)\n\n def unregister(self):\n self.client.remove_naming_instance(self.service_name,\n self.service_ip,\n self.service_port)\n\n def set_service(self, service_name, service_ip, service_port, service_group):\n self.service_name = service_name\n self.service_ip = service_ip\n self.service_port = service_port\n self.service_group = service_group\n\n async def beat_callback(self):\n self.client.send_heartbeat(self.service_name,\n self.service_ip,\n self.service_port)\n\n def load_conf(self, data_id, group):\n return self.client.get_config(data_id=data_id, group=group, no_snapshot=True)\n\n def add_conf_watcher(self, data_id, group, callback):\n self.client.add_config_watcher(data_id=data_id, group=group, cb=callback)\n\n\nif __name__ == \'__main__\':\n nacos_config = {\n "nacos_data_id":"test",\n "nacos_server_ip":"127.0.0.1",\n "nacos_namespace":"public",\n "nacos_groupName":"DEFAULT_GROUP",\n "nacos_user":"nacos",\n "nacos_password":"1234567"\n }\n nacos_data_id = nacos_config["nacos_data_id"]\n SERVER_ADDRESSES = nacos_config["nacos_server_ip"]\n NAMESPACE = nacos_config["nacos_namespace"]\n groupName = nacos_config["nacos_groupName"]\n user = nacos_config["nacos_user"]\n password = nacos_config["nacos_password"]\n # todo 将另一个路由对象(通常定义在其他模块或文件中)合并到主应用(app)中。\n # app.include_router(custom_api.router, tags=[\'test\'])\n service_ip = get_host_ip()\n client = NacosClient(SERVER_ADDRESSES, NAMESPACE, user, password)\n client.add_conf_watcher(nacos_data_id, groupName, nacos_config_callback)\n\n # 启动时,强制同步一次配置\n data_stream = client.load_conf(nacos_data_id, groupName)\n json_config = load_config(data_stream)\n'}},{key:"getCSharpCode",value:function(e){return'/*\nDemo for Basic Nacos Opreation\nApp.csproj\n\n\n \n\n*/\n\nusing Microsoft.Extensions.DependencyInjection;\nusing Nacos.V2;\nusing Nacos.V2.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n string serverAddr = "http://localhost:8848";\n string dataId = "'.concat(e.dataId,'";\n string group = "').concat(e.group,'";\n\n IServiceCollection services = new ServiceCollection();\n\n services.AddNacosV2Config(x =>\n {\n x.ServerAddresses = new List { serverAddr };\n x.Namespace = "cs-test";\n\n // swich to use http or rpc\n x.ConfigUseRpc = true;\n });\n\n IServiceProvider serviceProvider = services.BuildServiceProvider();\n var configSvc = serviceProvider.GetService();\n\n var content = await configSvc.GetConfig(dataId, group, 3000);\n Console.WriteLine(content);\n\n var listener = new ConfigListener();\n\n await configSvc.AddListener(dataId, group, listener);\n\n var isPublishOk = await configSvc.PublishConfig(dataId, group, "content");\n Console.WriteLine(isPublishOk);\n\n await Task.Delay(3000);\n content = await configSvc.GetConfig(dataId, group, 5000);\n Console.WriteLine(content);\n\n var isRemoveOk = await configSvc.RemoveConfig(dataId, group);\n Console.WriteLine(isRemoveOk);\n await Task.Delay(3000);\n\n content = await configSvc.GetConfig(dataId, group, 5000);\n Console.WriteLine(content);\n await Task.Delay(300000);\n }\n\n internal class ConfigListener : IListener\n {\n public void ReceiveConfigInfo(string configInfo)\n {\n Console.WriteLine("receive:" + configInfo);\n }\n }\n}\n\n/*\nRefer to document: https://github.com/nacos-group/nacos-sdk-csharp/tree/dev/samples/MsConfigApp\nDemo for ASP.NET Core Integration\nMsConfigApp.csproj\n\n\n \n\n*/\n\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Hosting;\nusing Serilog;\nusing Serilog.Events;\n\npublic class Program\n{\n public static void Main(string[] args)\n {\n Log.Logger = new LoggerConfiguration()\n .Enrich.FromLogContext()\n .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)\n .MinimumLevel.Override("System", LogEventLevel.Warning)\n .MinimumLevel.Debug()\n .WriteTo.Console()\n .CreateLogger();\n\n try\n {\n Log.ForContext().Information("Application starting...");\n CreateHostBuilder(args, Log.Logger).Build().Run();\n }\n catch (System.Exception ex)\n {\n Log.ForContext().Fatal(ex, "Application start-up failed!!");\n }\n finally\n {\n Log.CloseAndFlush();\n }\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args, Serilog.ILogger logger) =>\n Host.CreateDefaultBuilder(args)\n .ConfigureAppConfiguration((context, builder) =>\n {\n var c = builder.Build();\n builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), logAction: x => x.AddSerilog(logger));\n })\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.UseStartup().UseUrls("http://*:8787");\n })\n .UseSerilog();\n}\n ')}},{key:"openDialog",value:function(e){var t=this;this.setState({dialogvisible:!0}),this.record=e,setTimeout(function(){t.getData()})}},{key:"closeDialog",value:function(){this.setState({dialogvisible:!1})}},{key:"createCodeMirror",value:function(e,t){var n=this.refs.codepreview;n&&(n.innerHTML="",this.cm=window.CodeMirror(n,{value:t,mode:e,height:400,width:500,lineNumbers:!0,theme:"xq-light",lint:!0,tabMode:"indent",autoMatchParens:!0,textWrapping:!0,gutters:["CodeMirror-lint-markers"],extraKeys:{F1:function(e){e.setOption("fullScreen",!e.getOption("fullScreen"))},Esc:function(e){e.getOption("fullScreen")&&e.setOption("fullScreen",!1)}}}))}},{key:"changeTab",value:function(e,t){var n=this;setTimeout(function(){n[e]=!0,n.createCodeMirror("text/javascript",t)})}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e;return x.a.createElement("div",null,x.a.createElement(y.a,{title:e.sampleCode,style:{width:"80%"},visible:this.state.dialogvisible,footer:x.a.createElement("div",null),onClose:this.closeDialog.bind(this)},x.a.createElement("div",{style:{height:500}},x.a.createElement(H.a,{tip:e.loading,style:{width:"100%"},visible:this.state.loading},x.a.createElement(L.a,{shape:"text",style:{height:40,paddingBottom:10}},x.a.createElement(O,{title:"Java",key:1,onClick:this.changeTab.bind(this,"commoneditor1",this.defaultCode)}),x.a.createElement(O,{title:"Spring Boot",key:2,onClick:this.changeTab.bind(this,"commoneditor2",this.sprigboot_code)}),x.a.createElement(O,{title:"Spring Cloud",key:21,onClick:this.changeTab.bind(this,"commoneditor21",this.sprigcloud_code)}),x.a.createElement(O,{title:"Node.js",key:3,onClick:this.changeTab.bind(this,"commoneditor3",this.nodejsCode)}),x.a.createElement(O,{title:"C++",key:4,onClick:this.changeTab.bind(this,"commoneditor4",this.cppCode)}),x.a.createElement(O,{title:"Shell",key:5,onClick:this.changeTab.bind(this,"commoneditor5",this.shellCode)}),x.a.createElement(O,{title:"Python",key:6,onClick:this.changeTab.bind(this,"commoneditor6",this.pythonCode)}),x.a.createElement(O,{title:"C#",key:7,onClick:this.changeTab.bind(this,"commoneditor7",this.csharpCode)})),x.a.createElement("div",{ref:"codepreview"})))))}}]),n}(x.a.Component)).displayName="ShowCodeing",S=S))||S,S=(t(69),t(40)),S=t.n(S),z=(t(756),S.a.Row),D=S.a.Col,W=(0,n.a.config)(((S=function(e){Object(M.a)(n,e);var t=Object(k.a)(n);function n(e){return Object(_.a)(this,n),(e=t.call(this,e)).state={visible:!1,title:"",content:"",isok:!0,dataId:"",group:""},e}return Object(b.a)(n,[{key:"componentDidMount",value:function(){this.initData()}},{key:"initData",value:function(){var e=this.props.locale;this.setState({title:(void 0===e?{}:e).confManagement})}},{key:"openDialog",value:function(e){this.setState({visible:!0,title:e.title,content:e.content,isok:e.isok,dataId:e.dataId,group:e.group,message:e.message})}},{key:"closeDialog",value:function(){this.setState({visible:!1})}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e,t=x.a.createElement("div",{style:{textAlign:"right"}},x.a.createElement(c.a,{type:"primary",onClick:this.closeDialog.bind(this)},e.determine));return x.a.createElement("div",null,x.a.createElement(y.a,{visible:this.state.visible,footer:t,style:{width:555},onCancel:this.closeDialog.bind(this),onClose:this.closeDialog.bind(this),title:e.deletetitle},x.a.createElement("div",null,x.a.createElement(z,null,x.a.createElement(D,{span:"4",style:{paddingTop:16}},x.a.createElement(m.a,{type:"".concat(this.state.isok?"success":"delete","-filling"),style:{color:this.state.isok?"green":"red"},size:"xl"})),x.a.createElement(D,{span:"20"},x.a.createElement("div",null,x.a.createElement("h3",null,this.state.isok?e.deletedSuccessfully:e.deleteFailed),x.a.createElement("p",null,x.a.createElement("span",{style:{color:"#999",marginRight:5}},"Data ID"),x.a.createElement("span",{style:{color:"#c7254e"}},this.state.dataId)),x.a.createElement("p",null,x.a.createElement("span",{style:{color:"#999",marginRight:5}},"Group"),x.a.createElement("span",{style:{color:"#c7254e"}},this.state.group)),this.state.isok?"":x.a.createElement("p",{style:{color:"red"}},this.state.message)))))))}}]),n}(x.a.Component)).displayName="DeleteDialog",S=S))||S,S=(t(757),t(436)),B=t.n(S),U=(0,n.a.config)(((S=function(e){Object(M.a)(n,e);var t=Object(k.a)(n);function n(){return Object(_.a)(this,n),t.apply(this,arguments)}return Object(b.a)(n,[{key:"render",value:function(){var e=this.props,t=e.data,t=void 0===t?{}:t,n=e.height,e=e.locale,a=void 0===e?{}:e;return x.a.createElement("div",null,"notice"===t.modeType?x.a.createElement("div",{"data-spm-click":"gostr=/aliyun;locaid=notice"},x.a.createElement(B.a,{style:{marginBottom:1\n com.alibaba.nacos\n nacos-client\n ${latest.version}\n \n*/\npackage com.alibaba.nacos.example;\n\nimport java.util.Properties;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingFactory;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.listener.Event;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\n\n/**\n * @author nkorange\n */\npublic class NamingExample {\n\n public static void main(String[] args) throws NacosException {\n\n Properties properties = new Properties();\n properties.setProperty("serverAddr", System.getProperty("serverAddr"));\n properties.setProperty("namespace", System.getProperty("namespace"));\n\n NamingService naming = NamingFactory.createNamingService(properties);\n\n naming.registerInstance("'.concat(this.record.name,'", "11.11.11.11", 8888, "TEST1");\n\n naming.registerInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n System.out.println(naming.getAllInstances("').concat(this.record.name,'"));\n\n naming.deregisterInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n System.out.println(naming.getAllInstances("').concat(this.record.name,'"));\n\n naming.subscribe("').concat(this.record.name,'", new EventListener() {\n @Override\n public void onEvent(Event event) {\n System.out.println(((NamingEvent)event).getServiceName());\n System.out.println(((NamingEvent)event).getInstances());\n }\n });\n }\n}')}},{key:"getSpringCode",value:function(e){return'/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example\n* pom.xml\n \n com.alibaba.nacos\n nacos-spring-context\n ${latest.version}\n \n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring\npackage com.alibaba.nacos.example.spring;\n\nimport com.alibaba.nacos.api.annotation.NacosProperties;\nimport com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\n@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))\npublic class NacosConfiguration {\n\n}\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring/controller\npackage com.alibaba.nacos.example.spring.controller;\n\nimport com.alibaba.nacos.api.annotation.NacosInjected;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\n\nimport static org.springframework.web.bind.annotation.RequestMethod.GET;\n\n@Controller\n@RequestMapping("discovery")\npublic class DiscoveryController {\n\n @NacosInjected\n private NamingService namingService;\n\n @RequestMapping(value = "/get", method = GET)\n @ResponseBody\n public List get(@RequestParam String serviceName) throws NacosException {\n return namingService.getAllInstances(serviceName);\n }\n}'}},{key:"getSpringBootCode",value:function(e){return'/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example\n* pom.xml\n \n com.alibaba.boot\n nacos-discovery-spring-boot-starter\n ${latest.version}\n \n*/\n/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/resources\n* application.properties\n nacos.discovery.server-addr=127.0.0.1:8848\n*/\n// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/java/com/alibaba/nacos/example/spring/boot/controller\n\npackage com.alibaba.nacos.example.spring.boot.controller;\n\nimport com.alibaba.nacos.api.annotation.NacosInjected;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\n\nimport static org.springframework.web.bind.annotation.RequestMethod.GET;\n\n@Controller\n@RequestMapping("discovery")\npublic class DiscoveryController {\n\n @NacosInjected\n private NamingService namingService;\n\n @RequestMapping(value = "/get", method = GET)\n @ResponseBody\n public List get(@RequestParam String serviceName) throws NacosException {\n return namingService.getAllInstances(serviceName);\n }\n}'}},{key:"getSpringCloudCode",value:function(e){return"/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/\n* pom.xml\n \n org.springframework.cloud\n spring-cloud-starter-alibaba-nacos-discovery\n ${latest.version}\n \n*/\n\n// nacos-spring-cloud-provider-example\n\n/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/resources\n* application.properties\nserver.port=18080\nspring.application.name=".concat(this.record.name,'\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/java/com/alibaba/nacos/example/spring/cloud\npackage com.alibaba.nacos.example.spring.cloud;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class NacosProviderApplication {\n\n public static void main(String[] args) {\n SpringApplication.run(NacosProviderApplication.class, args);\n}\n\n @RestController\n class EchoController {\n @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)\n public String echo(@PathVariable String string) {\n return "Hello Nacos Discovery " + string;\n }\n }\n}\n\n// nacos-spring-cloud-consumer-example\n\n/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/resources\n* application.properties\nspring.application.name=micro-service-oauth2\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/java/com/alibaba/nacos/example/spring/cloud\npackage com.alibaba.nacos.example.spring.cloud;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class NacosConsumerApplication {\n\n @LoadBalanced\n @Bean\n public RestTemplate restTemplate() {\n return new RestTemplate();\n }\n\n public static void main(String[] args) {\n SpringApplication.run(NacosConsumerApplication.class, args);\n }\n\n @RestController\n public class TestController {\n\n private final RestTemplate restTemplate;\n\n @Autowired\n public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}\n\n @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)\n public String echo(@PathVariable String str) {\n return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);\n }\n }\n}')}},{key:"getNodejsCode",value:function(e){return"TODO"}},{key:"getCppCode",value:function(e){return"TODO"}},{key:"getShellCode",value:function(e){return"TODO"}},{key:"getPythonCode",value:function(e){return'/*\n* Demo for Nacos\n*/\nimport json\nimport socket\n\nimport nacos\n\n\ndef get_host_ip():\n res = socket.gethostbyname(socket.gethostname())\n return res\n\n\ndef load_config(content):\n _config = json.loads(content)\n return _config\n\n\ndef nacos_config_callback(args):\n content = args[\'raw_content\']\n load_config(content)\n\n\nclass NacosClient:\n service_name = None\n service_port = None\n service_group = None\n\n def __init__(self, server_endpoint, namespace_id, username=None, password=None):\n self.client = nacos.NacosClient(server_endpoint,\n namespace=namespace_id,\n username=username,\n password=password)\n self.endpoint = server_endpoint\n self.service_ip = get_host_ip()\n\n def register(self):\n self.client.add_naming_instance(self.service_name,\n self.service_ip,\n self.service_port,\n group_name=self.service_group)\n\n def modify(self, service_name, service_ip=None, service_port=None):\n self.client.modify_naming_instance(service_name,\n service_ip if service_ip else self.service_ip,\n service_port if service_port else self.service_port)\n\n def unregister(self):\n self.client.remove_naming_instance(self.service_name,\n self.service_ip,\n self.service_port)\n\n def set_service(self, service_name, service_ip, service_port, service_group):\n self.service_name = service_name\n self.service_ip = service_ip\n self.service_port = service_port\n self.service_group = service_group\n\n async def beat_callback(self):\n self.client.send_heartbeat(self.service_name,\n self.service_ip,\n self.service_port)\n\n def load_conf(self, data_id, group):\n return self.client.get_config(data_id=data_id, group=group, no_snapshot=True)\n\n def add_conf_watcher(self, data_id, group, callback):\n self.client.add_config_watcher(data_id=data_id, group=group, cb=callback)\n\n\nif __name__ == \'__main__\':\n nacos_config = {\n "nacos_data_id":"test",\n "nacos_server_ip":"127.0.0.1",\n "nacos_namespace":"public",\n "nacos_groupName":"DEFAULT_GROUP",\n "nacos_user":"nacos",\n "nacos_password":"1234567"\n }\n nacos_data_id = nacos_config["nacos_data_id"]\n SERVER_ADDRESSES = nacos_config["nacos_server_ip"]\n NAMESPACE = nacos_config["nacos_namespace"]\n groupName = nacos_config["nacos_groupName"]\n user = nacos_config["nacos_user"]\n password = nacos_config["nacos_password"]\n # todo 将另一个路由对象(通常定义在其他模块或文件中)合并到主应用(app)中。\n # app.include_router(custom_api.router, tags=[\'test\'])\n service_ip = get_host_ip()\n client = NacosClient(SERVER_ADDRESSES, NAMESPACE, user, password)\n client.add_conf_watcher(nacos_data_id, groupName, nacos_config_callback)\n\n # 启动时,强制同步一次配置\n data_stream = client.load_conf(nacos_data_id, groupName)\n json_config = load_config(data_stream)\n #设定服务\n client.set_service(json_config["service_name"], json_config.get("service_ip", service_ip), service_port, groupName)\n #注册服务\n client.register()\n #下线服务\n client.unregister()\n'}},{key:"getCSharpCode",value:function(e){return'/* Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/\nDemo for Basic Nacos Opreation\nApp.csproj\n\n\n \n\n*/\n\nusing Microsoft.Extensions.DependencyInjection;\nusing Nacos.V2;\nusing Nacos.V2.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n IServiceCollection services = new ServiceCollection();\n\n services.AddNacosV2Naming(x =>\n {\n x.ServerAddresses = new List { "http://localhost:8848/" };\n x.Namespace = "cs-test";\n\n // swich to use http or rpc\n x.NamingUseRpc = true;\n });\n\n IServiceProvider serviceProvider = services.BuildServiceProvider();\n var namingSvc = serviceProvider.GetService();\n\n await namingSvc.RegisterInstance("'.concat(this.record.name,'", "11.11.11.11", 8888, "TEST1");\n\n await namingSvc.RegisterInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(await namingSvc.GetAllInstances("').concat(this.record.name,'")));\n\n await namingSvc.DeregisterInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n var listener = new EventListener();\n\n await namingSvc.Subscribe("').concat(this.record.name,'", listener);\n }\n\n internal class EventListener : IEventListener\n {\n public Task OnEvent(IEvent @event)\n {\n Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(@event));\n return Task.CompletedTask;\n }\n }\n}\n\n/* Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/\nDemo for ASP.NET Core Integration\nApp.csproj\n\n\n \n\n*/\n\n/* Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/blob/dev/samples/App1/appsettings.json\n* appsettings.json\n{\n "nacos": {\n "ServerAddresses": [ "http://localhost:8848" ],\n "DefaultTimeOut": 15000,\n "Namespace": "cs",\n "ServiceName": "App1",\n "GroupName": "DEFAULT_GROUP",\n "ClusterName": "DEFAULT",\n "Port": 0,\n "Weight": 100,\n "RegisterEnabled": true,\n "InstanceEnabled": true,\n "Ephemeral": true,\n "NamingUseRpc": true,\n "NamingLoadCacheAtStart": ""\n }\n}\n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/blob/dev/samples/App1/Startup.cs\nusing Nacos.AspNetCore.V2;\n\npublic class Startup\n{\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n {\n // ....\n services.AddNacosAspNet(Configuration);\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // ....\n }\n}\n ')}},{key:"openDialog",value:function(e){var t=this;this.setState({dialogvisible:!0}),this.record=e,setTimeout(function(){t.getData()})}},{key:"closeDialog",value:function(){this.setState({dialogvisible:!1})}},{key:"createCodeMirror",value:function(e,t){var n=this.refs.codepreview;n&&(n.innerHTML="",this.cm=window.CodeMirror(n,{value:t,mode:e,height:400,width:500,lineNumbers:!0,theme:"xq-light",lint:!0,tabMode:"indent",autoMatchParens:!0,textWrapping:!0,gutters:["CodeMirror-lint-markers"],extraKeys:{F1:function(e){e.setOption("fullScreen",!e.getOption("fullScreen"))},Esc:function(e){e.getOption("fullScreen")&&e.setOption("fullScreen",!1)}}}),this.cm.setSize("auto","490px"))}},{key:"changeTab",value:function(e,t){var n=this;setTimeout(function(){n[e]=!0,n.createCodeMirror("text/javascript",t)})}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e;return O.a.createElement("div",null,O.a.createElement(o.a,{title:e.sampleCode,style:{width:"80%"},visible:this.state.dialogvisible,footer:O.a.createElement("div",null),onClose:this.closeDialog.bind(this)},O.a.createElement("div",{style:{height:500}},O.a.createElement(h.a,{tip:e.loading,style:{width:"100%"},visible:this.state.loading},O.a.createElement(m.a,{shape:"text",style:{height:40,paddingBottom:10}},O.a.createElement(g,{title:"Java",key:0,onClick:this.changeTab.bind(this,"commoneditor1",this.defaultCode)}),O.a.createElement(g,{title:"Spring",key:1,onClick:this.changeTab.bind(this,"commoneditor1",this.springCode)}),O.a.createElement(g,{title:"Spring Boot",key:2,onClick:this.changeTab.bind(this,"commoneditor2",this.sprigbootCode)}),O.a.createElement(g,{title:"Spring Cloud",key:21,onClick:this.changeTab.bind(this,"commoneditor21",this.sprigcloudCode)}),O.a.createElement(g,{title:"Node.js",key:3,onClick:this.changeTab.bind(this,"commoneditor3",this.nodejsCode)}),O.a.createElement(g,{title:"C++",key:4,onClick:this.changeTab.bind(this,"commoneditor4",this.cppCode)}),O.a.createElement(g,{title:"Shell",key:5,onClick:this.changeTab.bind(this,"commoneditor5",this.shellCode)}),O.a.createElement(g,{title:"Python",key:6,onClick:this.changeTab.bind(this,"commoneditor6",this.pythonCode)}),O.a.createElement(g,{title:"C#",key:7,onClick:this.changeTab.bind(this,"commoneditor7",this.csharpCode)})),O.a.createElement("div",{ref:"codepreview"})))))}}]),n}(O.a.Component)).displayName="ShowServiceCodeing",f=f))||f,Y=t(51),I=t(146),A=(t(778),t(22)),R=L.a.Item,H=d.a.Row,F=d.a.Col,z=T.a.Column,d=(0,n.a.config)(((f=function(e){Object(u.a)(n,e);var t=Object(c.a)(n);function n(e){var a;return Object(s.a)(this,n),(a=t.call(this,e)).getQueryLater=function(){setTimeout(function(){return a.queryServiceList()})},a.showcode=function(){setTimeout(function(){return a.queryServiceList()})},a.setNowNameSpace=function(e,t,n){return a.setState({nowNamespaceName:e,nowNamespaceId:t,nowNamespaceDesc:n})},a.rowColor=function(e){return{className:e.healthyInstanceCount?"":"row-bg-red"}},a.editServiceDialog=O.a.createRef(),a.showcode=O.a.createRef(),a.state={loading:!1,total:0,pageSize:10,currentPage:1,dataSource:[],search:{serviceName:Object(p.b)("serviceNameParam")||"",groupName:Object(p.b)("groupNameParam")||""},hasIpCount:!("false"===localStorage.getItem("hasIpCount"))},a.field=new i.a(Object(l.a)(a)),a}return Object(a.a)(n,[{key:"openLoading",value:function(){this.setState({loading:!0})}},{key:"closeLoading",value:function(){this.setState({loading:!1})}},{key:"openEditServiceDialog",value:function(){try{this.editServiceDialog.current.getInstance().show(this.state.service)}catch(e){}}},{key:"queryServiceList",value:function(){var n=this,e=this.state,t=e.currentPage,a=e.pageSize,r=e.search,o=e.withInstances,o=void 0!==o&&o,e=e.hasIpCount,e=["hasIpCount=".concat(e),"withInstances=".concat(o),"pageNo=".concat(t),"pageSize=".concat(a),"serviceNameParam=".concat(r.serviceName),"groupNameParam=".concat(r.groupName)];Object(p.f)({serviceNameParam:r.serviceName,groupNameParam:r.groupName}),this.openLoading(),Object(p.e)({url:"v3/console/ns/service/list?".concat(e.join("&")),success:function(e){var e=e.data,e=void 0===e?{}:e,t=e.count,e=e.serviceList;n.setState({dataSource:void 0===e?[]:e,total:void 0===t?0:t,loading:!1})},error:function(){return n.setState({dataSource:[],total:0,currentPage:0,loading:!1})}})}},{key:"showSampleCode",value:function(e){this.showcode.current.getInstance().openDialog(e)}},{key:"querySubscriber",value:function(e){var t=e.name,e=e.groupName,n=this.state.nowNamespaceId;this.props.history.push(Object(D.a)("/subscriberList",{namespace:n,name:t,groupName:e}))}},{key:"handlePageSizeChange",value:function(e){var t=this;this.setState({pageSize:e},function(){return t.queryServiceList()})}},{key:"deleteService",value:function(e){var t=this,n=this.props.locale,n=void 0===n?{}:n,a=n.prompt,n=n.promptDelete;o.a.confirm({title:a,content:n,onOk:function(){Object(p.e)({method:"DELETE",url:"v3/console/ns/service?serviceName=".concat(e.name,"&groupName=").concat(e.groupName),dataType:"json",beforeSend:function(){return t.openLoading()},success:function(e){0!==e.code?r.a.error(e.message||"删除服务失败"):(r.a.success("服务删除成功"),t.queryServiceList())},error:function(e){var t;r.a.error((null==(t=e.data)?void 0:t.responseText)||e.statusText||"请求失败")},complete:function(){return t.closeLoading()}})}})}},{key:"render",value:function(){var a=this,e=this.props.locale,t=void 0===e?{}:e,e=t.pubNoData,n=t.serviceList,r=t.serviceName,o=t.serviceNamePlaceholder,i=t.groupName,s=t.groupNamePlaceholder,l=t.hiddenEmptyService,u=t.query,c=t.create,d=t.operation,f=t.detail,p=t.sampleCode,h=t.deleteAction,m=t.subscriber,g=this.state,y=g.search,v=g.nowNamespaceName,_=g.nowNamespaceId,b=g.nowNamespaceDesc,g=g.hasIpCount,w=this.field,M=w.init,w=w.getValue;return this.init=M,this.getValue=w,O.a.createElement("div",{className:"main-container service-management"},O.a.createElement(Y.a,{title:n,desc:b,namespaceId:_,namespaceName:v,nameSpace:!0}),O.a.createElement(N.a,{setNowNameSpace:this.setNowNameSpace,namespaceCallBack:this.getQueryLater}),O.a.createElement(H,{className:"demo-row",style:{marginBottom:10,padding:0}},O.a.createElement(F,{span:"24"},O.a.createElement(L.a,{inline:!0,field:this.field},O.a.createElement(R,{label:""},O.a.createElement(C.a,{type:"primary",onClick:function(){return a.openEditServiceDialog()}},c)),O.a.createElement(R,{label:r},O.a.createElement(E.a,{placeholder:o,style:{width:200},value:y.serviceName,onChange:function(e){return a.setState({search:Object(x.a)(Object(x.a)({},y),{},{serviceName:e})})},onPressEnter:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})}})),O.a.createElement(R,{label:i},O.a.createElement(E.a,{placeholder:s,style:{width:200},value:y.groupName,onChange:function(e){return a.setState({search:Object(x.a)(Object(x.a)({},y),{},{groupName:e})})},onPressEnter:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})}})),O.a.createElement(L.a.Item,{label:"".concat(l)},O.a.createElement(S.a,{checked:g,onChange:function(e){return a.setState({hasIpCount:e,currentPage:1},function(){localStorage.setItem("hasIpCount",e),a.queryServiceList()})}})),O.a.createElement(R,{label:""},O.a.createElement(C.a,{type:"primary",onClick:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})},style:{marginRight:10}},u))))),O.a.createElement(H,{style:{padding:0}},O.a.createElement(F,{span:"24",style:{padding:0}},O.a.createElement(T.a,{dataSource:this.state.dataSource,locale:{empty:e},rowProps:function(e){return a.rowColor(e)},loading:this.state.loading},O.a.createElement(z,{title:t.columnServiceName,dataIndex:"name"}),O.a.createElement(z,{title:t.groupName,dataIndex:"groupName"}),O.a.createElement(z,{title:t.columnClusterCount,dataIndex:"clusterCount"}),O.a.createElement(z,{title:t.columnIpCount,dataIndex:"ipCount"}),O.a.createElement(z,{title:t.columnHealthyInstanceCount,dataIndex:"healthyInstanceCount"}),O.a.createElement(z,{title:t.columnTriggerFlag,dataIndex:"triggerFlag"}),O.a.createElement(z,{title:d,align:"center",cell:function(e,t,n){return O.a.createElement("div",null,O.a.createElement("a",{onClick:function(){var e=n.name,t=n.groupName;a.props.history.push(Object(D.a)("/serviceDetail",{name:e,groupName:t}))},style:{marginRight:5}},f),O.a.createElement("span",{style:{marginRight:5}},"|"),O.a.createElement("a",{style:{marginRight:5},onClick:function(){return a.showSampleCode(n)}},p),O.a.createElement("span",{style:{marginRight:5}},"|"),O.a.createElement("a",{style:{marginRight:5},onClick:function(){return a.querySubscriber(n)}},m),O.a.createElement("span",{style:{marginRight:5}},"|"),O.a.createElement("a",{onClick:function(){return a.deleteService(n)},style:{marginRight:5}},h))}})))),O.a.createElement("div",{style:{marginTop:10,textAlign:"right"}},O.a.createElement(k.a,{current:this.state.currentPage,pageSizeList:A.f,pageSizePosition:"start",pageSizeSelector:"dropdown",popupProps:{align:"bl tl"},total:this.state.total,pageSize:this.state.pageSize,totalRender:function(e){return O.a.createElement(I.a,{locale:t,total:e})},onPageSizeChange:function(e){return a.handlePageSizeChange(e)},onChange:function(e){return a.setState({currentPage:e},function(){return a.queryServiceList()})}})),O.a.createElement(j,{ref:this.showcode}),O.a.createElement(P.a,{ref:this.editServiceDialog,openLoading:function(){return a.openLoading()},closeLoading:function(){return a.closeLoading()},queryServiceList:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})}}))}}]),n}(O.a.Component)).displayName="ServiceList",t=f))||t;e.a=d},function(e,t,n){"use strict";n(67);var a=n(46),u=n.n(a),a=(n(35),n(17)),c=n.n(a),a=(n(66),n(21)),d=n.n(a),a=(n(34),n(20)),f=n.n(a),a=(n(93),n(55)),p=n.n(a),a=(n(38),n(2)),h=n.n(a),a=(n(37),n(10)),m=n.n(a),i=n(12),s=n(13),l=n(23),g=n(15),y=n(14),a=(n(27),n(6)),a=n.n(a),r=n(0),v=n.n(r),r=n(30),_=n(45),b=n(53),w=n(32),o=(n(49),n(28)),M=n.n(o),k=(n(168),h.a.Item),S={labelCol:{fixedSpan:4},wrapperCol:{span:19}},E=(0,a.a.config)(((o=function(e){Object(g.a)(o,e);var r=Object(y.a)(o);function o(){var e;Object(i.a)(this,o);for(var t=arguments.length,n=new Array(t),a=0;ao&&v.a.createElement(u.a,{className:"users-pagination",current:i,total:n.totalCount,pageSize:o,onChange:function(e){return t.setState({pageNo:e},function(){return t.getUsers()})}}),v.a.createElement(E,{visible:s,onOk:function(e){return Object(_.c)(e).then(function(e){return t.setState({pageNo:1},function(){return t.getUsers()}),e})},onCancel:function(){return t.colseCreateUser()}}),v.a.createElement(x.a,{visible:l,username:e,onOk:function(e){return Object(_.k)(e).then(function(e){return t.getUsers(),e})},onCancel:function(){return t.setState({passwordResetUser:void 0,passwordResetUserVisible:!1})}}))}}]),n}(v.a.Component)).displayName="UserManagement",n=o))||n)||n;t.a=r},function(e,t,n){"use strict";n(67);var a=n(46),l=n.n(a),a=(n(35),n(17)),u=n.n(a),c=n(32),a=(n(66),n(21)),d=n.n(a),a=(n(34),n(20)),f=n.n(a),a=(n(93),n(55)),p=n.n(a),a=(n(38),n(2)),h=n.n(a),a=(n(37),n(10)),m=n.n(a),i=n(12),s=n(13),g=n(23),y=n(15),v=n(14),a=(n(27),n(6)),a=n.n(a),r=n(0),_=n.n(r),r=n(30),b=n(45),o=n(86),w=n(53),M=(n(49),n(28)),k=n.n(M),M=(n(59),n(29)),S=n.n(M),E=h.a.Item,x=S.a.Option,C={labelCol:{fixedSpan:4},wrapperCol:{span:19}},T=Object(r.b)(function(e){return{namespaces:e.namespace.namespaces}},{getNamespaces:o.b,searchRoles:b.l})(M=(0,a.a.config)(((M=function(e){Object(y.a)(o,e);var r=Object(v.a)(o);function o(){var t;Object(i.a)(this,o);for(var e=arguments.length,n=new Array(e),a=0;ai&&_.a.createElement(l.a,{className:"users-pagination",current:s,total:t.totalCount,pageSize:i,onChange:function(e){return a.setState({pageNo:e},function(){return a.getPermissions()})}}),_.a.createElement(T,{visible:n,onOk:function(e){return Object(b.a)(e).then(function(e){return a.setState({pageNo:1},function(){return a.getPermissions()}),e})},onCancel:function(){return a.colseCreatePermission()}}))}}]),n}(_.a.Component)).displayName="PermissionsManagement",n=M))||n)||n);t.a=r},function(e,t,n){"use strict";n(67);var a=n(46),l=n.n(a),a=(n(35),n(17)),u=n.n(a),a=(n(66),n(21)),c=n.n(a),a=(n(34),n(20)),d=n.n(a),a=(n(93),n(55)),f=n.n(a),a=(n(38),n(2)),p=n.n(a),a=(n(37),n(10)),h=n.n(a),i=n(12),s=n(13),m=n(23),g=n(15),y=n(14),a=(n(27),n(6)),a=n.n(a),r=n(0),v=n.n(r),r=n(30),_=n(45),b=n(53),o=(n(59),n(29)),w=n.n(o),o=(n(49),n(28)),M=n.n(o),k=p.a.Item,S={labelCol:{fixedSpan:4},wrapperCol:{span:19}},E=Object(r.b)(function(e){return{users:e.authority.users}},{searchUsers:_.m})(o=(0,a.a.config)(((o=function(e){Object(g.a)(o,e);var r=Object(y.a)(o);function o(){var t;Object(i.a)(this,o);for(var e=arguments.length,n=new Array(e),a=0;ao&&v.a.createElement(l.a,{className:"users-pagination",current:i,total:t.totalCount,pageSize:o,onChange:function(e){return a.setState({pageNo:e},function(){return a.getRoles()})}}),v.a.createElement(E,{visible:s,onOk:function(e){return Object(_.b)(e).then(function(e){return a.getRoles(),e})},onCancel:function(){return a.colseCreateRole()}}))}}]),n}(v.a.Component)).displayName="RolesManagement",n=o))||n)||n);t.a=r},function(e,t,n){"use strict";n(35);function l(e){var t=void 0===(t=localStorage.token)?"{}":t,t=(Object(_.c)(t)&&JSON.parse(t)||{}).globalAdmin,n=[];return"naming"===e?n.push(b):"config"===e?n.push(w):n.push(w,b),t&&n.push(M),n.push(k),n.push(S),n.push(E),n.filter(function(e){return e})}var a=n(17),u=n.n(a),a=(n(47),n(24)),c=n.n(a),a=(n(43),n(26)),d=n.n(a),r=n(12),o=n(13),i=n(15),s=n(14),a=(n(27),n(6)),a=n.n(a),f=n(19),p=(n(84),n(50)),h=n.n(p),p=n(0),m=n.n(p),p=n(39),g=n(30),y=n(108),v=n(52),_=n(48),b={key:"serviceManagementVirtual",children:[{key:"serviceManagement",url:"/serviceManagement"},{key:"subscriberList",url:"/subscriberList"}]},w={key:"configurationManagementVirtual",children:[{key:"configurationManagement",url:"/configurationManagement"},{key:"historyRollback",url:"/historyRollback"},{key:"listeningToQuery",url:"/listeningToQuery"}]},M={key:"authorityControl",children:[{key:"userList",url:"/userManagement"},{key:"roleManagement",url:"/rolesManagement"},{key:"privilegeManagement",url:"/permissionsManagement"}]},k={key:"namespace",url:"/namespace"},S={key:"clusterManagementVirtual",children:[{key:"clusterManagement",url:"/clusterManagement"}]},E={key:"settingCenter",url:"/settingCenter"},x=(n(386),h.a.SubMenu),C=h.a.Item,p=(n=Object(g.b)(function(e){return Object(f.a)(Object(f.a)({},e.locale),e.base)},{getState:v.e,getNotice:v.d,getGuide:v.c}),g=a.a.config,Object(p.g)(a=n(a=g(((v=function(e){Object(i.a)(n,e);var t=Object(s.a)(n);function n(e){return Object(r.a)(this,n),(e=t.call(this,e)).state={visible:!0},e}return Object(o.a)(n,[{key:"componentDidMount",value:function(){this.props.getState(),this.props.getNotice(),this.props.getGuide()}},{key:"goBack",value:function(){this.props.history.goBack()}},{key:"navTo",value:function(e){var t=this.props.location.search,t=new URLSearchParams(t);t.set("namespace",window.nownamespace),t.set("namespaceShowName",window.namespaceShowName),this.props.history.push([e,"?",t.toString()].join(""))}},{key:"isCurrentPath",value:function(e){return e===this.props.location.pathname?"current-path next-selected":void 0}},{key:"defaultOpenKeys",value:function(){for(var t=this,e=l(this.props.functionMode),n=0,a=e.length;nthis.state.pageSize&&S.a.createElement("div",{style:{marginTop:10,textAlign:"right"}},S.a.createElement(v.a,{current:this.state.pageNo,total:a,pageSize:this.state.pageSize,onChange:function(e){return t.setState({pageNo:e},function(){return t.querySubscriberList()})}}))))}}]),n}(S.a.Component)).displayName="SubscriberList",d=n))||d)||d;t.a=f},function(e,t,n){"use strict";n(54);var a=n(36),c=n.n(a),a=(n(67),n(46)),d=n.n(a),a=(n(179),n(78)),f=n.n(a),a=(n(37),n(10)),p=n.n(a),a=(n(34),n(20)),h=n.n(a),a=(n(35),n(17)),r=n.n(a),a=(n(47),n(24)),o=n.n(a),a=(n(49),n(28)),i=n.n(a),s=n(12),l=n(13),u=n(23),m=n(15),g=n(14),a=(n(27),n(6)),a=n.n(a),y=(n(421),n(123)),v=n.n(y),y=(n(66),n(21)),_=n.n(y),y=(n(69),n(40)),y=n.n(y),b=(n(38),n(2)),w=n.n(b),b=n(0),M=n.n(b),k=n(1),b=n(144),S=n.n(b),E=n(51),x=(n(781),w.a.Item),C=y.a.Row,T=y.a.Col,L=_.a.Column,O=v.a.Panel,y=(0,a.a.config)(((b=function(e){Object(m.a)(a,e);var t=Object(g.a)(a);function a(e){var n;return Object(s.a)(this,a),(n=t.call(this,e)).getQueryLater=function(){setTimeout(function(){return n.queryClusterStateList()})},n.setNowNameSpace=function(e,t){return n.setState({nowNamespaceName:e,nowNamespaceId:t})},n.rowColor=function(e){return{className:(e.voteFor,"")}},n.state={loading:!1,total:0,pageSize:10,currentPage:1,keyword:"",dataSource:[]},n.field=new i.a(Object(u.a)(n)),n}return Object(l.a)(a,[{key:"componentDidMount",value:function(){this.getQueryLater()}},{key:"openLoading",value:function(){this.setState({loading:!0})}},{key:"closeLoading",value:function(){this.setState({loading:!1})}},{key:"queryClusterStateList",value:function(){var n=this,e=this.state,t=e.currentPage,a=e.pageSize,r=e.keyword,e=e.withInstances,e=["withInstances=".concat(void 0!==e&&e),"pageNo=".concat(t),"pageSize=".concat(a),"keyword=".concat(r)];Object(k.e)({url:"v3/console/core/cluster/nodes?".concat(e.join("&")),beforeSend:function(){return n.openLoading()},success:function(){var e=0this.state.pageSize&&M.a.createElement("div",{style:{marginTop:10,textAlign:"right"}},M.a.createElement(d.a,{current:this.state.currentPage,total:this.state.total,pageSize:this.state.pageSize,onChange:function(e){return t.setState({currentPage:e},function(){return t.queryClusterStateList()})}}))))}}]),a}(M.a.Component)).displayName="ClusterNodeList",n=b))||n;t.a=y},function(e,t,n){"use strict";n(34);var a=n(20),i=n.n(a),s=n(12),l=n(13),u=n(15),c=n(14),a=(n(27),n(6)),a=n.n(a),r=n(19),o=(n(114),n(75)),o=n.n(o),d=n(0),f=n.n(d),p=(n(784),n(51)),d=n(87),h=n(148),m=n(149),g=n(30),y=n(22),v=o.a.Group,g=Object(g.b)(function(e){return Object(r.a)({},e.locale)},{changeLanguage:d.a,changeTheme:h.a,changeNameShow:m.a})(o=(0,a.a.config)(((n=function(e){Object(u.a)(o,e);var r=Object(c.a)(o);function o(e){Object(s.a)(this,o),e=r.call(this,e);var t=localStorage.getItem(y.p),n=localStorage.getItem(y.j),a=localStorage.getItem(y.g);return e.state={theme:"dark"===t?"dark":"light",language:"en-US"===a?"en-US":"zh-CN",nameShow:"select"===n?"select":"label"},e}return Object(l.a)(o,[{key:"newTheme",value:function(e){this.setState({theme:e})}},{key:"newLanguage",value:function(e){this.setState({language:e})}},{key:"newNameShow",value:function(e){this.setState({nameShow:e})}},{key:"submit",value:function(){var e=this.props,t=e.changeLanguage,n=e.changeTheme,e=e.changeNameShow,a=this.state.language,r=this.state.theme,o=this.state.nameShow;t(a),n(r),e(o)}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e,t=[{value:"light",label:e.settingLight},{value:"dark",label:e.settingDark}],n=[{value:"select",label:e.settingShowSelect},{value:"label",label:e.settingShowLabel}];return f.a.createElement(f.a.Fragment,null,f.a.createElement(p.a,{title:e.settingTitle}),f.a.createElement("div",{className:"setting-box"},f.a.createElement("div",{className:"text-box"},f.a.createElement("div",{className:"setting-checkbox"},f.a.createElement("div",{className:"setting-span"},e.settingTheme),f.a.createElement(v,{dataSource:t,value:this.state.theme,onChange:this.newTheme.bind(this)})),f.a.createElement("div",{className:"setting-checkbox"},f.a.createElement("div",{className:"setting-span"},e.settingLocale),f.a.createElement(v,{dataSource:[{value:"en-US",label:"English"},{value:"zh-CN",label:"中文"}],value:this.state.language,onChange:this.newLanguage.bind(this)})),f.a.createElement("div",{className:"setting-checkbox"},f.a.createElement("div",{className:"setting-span"},e.settingShow),f.a.createElement(v,{dataSource:n,value:this.state.nameShow,onChange:this.newNameShow.bind(this)}))),f.a.createElement(i.a,{type:"primary",onClick:this.submit.bind(this)},e.settingSubmit)))}}]),o}(f.a.Component)).displayName="SettingCenter",o=n))||o)||o;t.a=g},function(e,t,V){"use strict";V.r(t),function(e){V(54);var t=V(36),a=V.n(t),t=(V(27),V(6)),r=V.n(t),o=V(12),i=V(13),s=V(15),l=V(14),n=V(19),t=V(0),u=V.n(t),t=V(25),t=V.n(t),c=V(125),d=V(429),f=V(440),p=V(30),h=V(39),m=V(73),g=(V(477),V(449)),y=V(22),v=V(450),_=V(451),b=V(443),w=V(452),M=V(453),k=V(444),S=V(454),E=V(455),x=V(456),C=V(457),T=V(458),L=V(441),O=V(445),D=V(442),N=V(459),P=V(460),j=V(446),I=V(447),A=V(448),R=V(438),H=V(461),Y=V(439),F=V(87),z=V(52),W=V(148),B=V(149),e=(V(785),e.hot,localStorage.getItem(y.g)||localStorage.setItem(y.g,"zh-CN"===navigator.language?"zh-CN":"en-US"),Object(c.b)(Object(n.a)(Object(n.a)({},Y.a),{},{routing:d.routerReducer}))),Y=Object(c.d)(e,Object(c.c)(Object(c.a)(f.a),window[y.l]?window[y.l]():function(e){return e})),U=[{path:"/",exact:!0,render:function(){return u.a.createElement(h.a,{to:"/welcome"})}},{path:"/welcome",component:R.a},{path:"/namespace",component:b.a},{path:"/newconfig",component:w.a},{path:"/configsync",component:M.a},{path:"/configdetail",component:k.a},{path:"/configeditor",component:S.a},{path:"/historyDetail",component:E.a},{path:"/configRollback",component:x.a},{path:"/historyRollback",component:C.a},{path:"/listeningToQuery",component:T.a},{path:"/configurationManagement",component:L.a},{path:"/serviceManagement",component:O.a},{path:"/serviceDetail",component:D.a},{path:"/subscriberList",component:N.a},{path:"/clusterManagement",component:P.a},{path:"/userManagement",component:j.a},{path:"/rolesManagement",component:A.a},{path:"/permissionsManagement",component:I.a},{path:"/settingCenter",component:H.a}],e=Object(p.b)(function(e){return Object(n.a)(Object(n.a)({},e.locale),e.base)},{changeLanguage:F.a,getState:z.e,changeTheme:W.a,changeNameShow:B.a})(d=function(e){Object(s.a)(n,e);var t=Object(l.a)(n);function n(e){return Object(o.a)(this,n),(e=t.call(this,e)).state={shownotice:"none",noticecontent:"",nacosLoading:{}},e}return Object(i.a)(n,[{key:"componentDidMount",value:function(){this.props.getState();var e=localStorage.getItem(y.g),t=localStorage.getItem(y.p),n=localStorage.getItem(y.j);this.props.changeLanguage(e),this.props.changeTheme(t),this.props.changeNameShow(n)}},{key:"router",get:function(){var e=this.props,t=e.loginPageEnabled,e=e.consoleUiEnable;return u.a.createElement(m.a,null,u.a.createElement(h.d,null,t&&"false"===t?null:u.a.createElement(h.b,{path:"/login",component:v.a}),u.a.createElement(h.b,{path:"/register",component:_.a}),u.a.createElement(g.a,null,e&&"true"===e&&U.map(function(e){return u.a.createElement(h.b,Object.assign({key:e.path},e))}))))}},{key:"render",value:function(){var e=this.props,t=e.locale,e=e.loginPageEnabled;return u.a.createElement(a.a,Object.assign({className:"nacos-loading",shape:"flower",tip:"loading...",visible:!e,fullScreen:!0},this.state.nacosLoading),u.a.createElement(r.a,{locale:t},this.router))}}]),n}(u.a.Component))||d;t.a.render(u.a.createElement(p.a,{store:Y},u.a.createElement(e,null)),document.getElementById("root"))}.call(this,V(463)(e))},function(e,t){e.exports=function(e){var t;return e.webpackPolyfill||((t=Object.create(e)).children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),Object.defineProperty(t,"exports",{enumerable:!0}),t.webpackPolyfill=1),t}},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(I,e,t){"use strict"; +var S=P(706),o=P(707),s=P(708);function n(){return d.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function l(e,t){if(n()=n())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+n().toString(16)+" bytes");return 0|e}function f(e,t){if(d.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;var n=(e="string"!=typeof e?""+e:e).length;if(0===n)return 0;for(var a=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return L(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return O(e).length;default:if(a)return L(e).length;t=(""+t).toLowerCase(),a=!0}}function t(e,t,n){var a,r=!1;if((t=void 0===t||t<0?0:t)>this.length)return"";if((n=void 0===n||n>this.length?this.length:n)<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e=e||"utf8";;)switch(e){case"hex":var o=this,i=t,s=n,l=o.length;(!s||s<0||l=e.length){if(r)return-1;n=e.length-1}else if(n<0){if(!r)return-1;n=0}if("string"==typeof t&&(t=d.from(t,a)),d.isBuffer(t))return 0===t.length?-1:m(e,t,n,a,r);if("number"==typeof t)return t&=255,d.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?(r?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(e,t,n):m(e,[t],n,a,r);throw new TypeError("val must be string, number or Buffer")}function m(e,t,n,a,r){var o=1,i=e.length,s=t.length;if(void 0!==a&&("ucs2"===(a=String(a).toLowerCase())||"ucs-2"===a||"utf16le"===a||"utf-16le"===a)){if(e.length<2||t.length<2)return-1;i/=o=2,s/=2,n/=2}function l(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(r)for(var u=-1,c=n;c>8,r.push(n%256),r.push(a);return r}(t,e.length-n),e,n,a)}function E(e,t,n){n=Math.min(e.length,n);for(var a=[],r=t;r>>10&1023|55296),c=56320|1023&c),a.push(c),r+=d}var f=a,p=f.length;if(p<=v)return String.fromCharCode.apply(String,f);for(var h="",m=0;mt)&&(e+=" ... "),""},d.prototype.compare=function(e,t,n,a,r){if(!d.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===n&&(n=e?e.length:0),void 0===a&&(a=0),void 0===r&&(r=this.length),(t=void 0===t?0:t)<0||n>e.length||a<0||r>this.length)throw new RangeError("out of range index");if(r<=a&&n<=t)return 0;if(r<=a)return-1;if(n<=t)return 1;if(this===e)return 0;for(var o=(r>>>=0)-(a>>>=0),i=(n>>>=0)-(t>>>=0),s=Math.min(o,i),l=this.slice(a,r),u=e.slice(t,n),c=0;cthis.length)throw new RangeError("Attempt to write outside buffer bounds");a=a||"utf8";for(var o,i,s,l=!1;;)switch(a){case"hex":var u=this,c=e,d=t,f=n,p=(d=Number(d)||0,u.length-d);if((!f||p<(f=Number(f)))&&(f=p),(p=c.length)%2!=0)throw new TypeError("Invalid hex string");p/2e.length)throw new RangeError("Index out of range")}function w(e,t,n,a){t<0&&(t=65535+t+1);for(var r=0,o=Math.min(e.length-n,2);r>>8*(a?r:1-r)}function M(e,t,n,a){t<0&&(t=4294967295+t+1);for(var r=0,o=Math.min(e.length-n,4);r>>8*(a?r:3-r)&255}function k(e,t,n,a){if(n+a>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function x(e,t,n,a,r){return r||k(e,0,n,4),o.write(e,t,n,a,23,4),n+4}function C(e,t,n,a,r){return r||k(e,0,n,8),o.write(e,t,n,a,52,8),n+8}d.prototype.slice=function(e,t){var n=this.length;if((e=~~e)<0?(e+=n)<0&&(e=0):n>>8):w(this,e,t,!0),t+2},d.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,2,65535,0),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):w(this,e,t,!1),t+2},d.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,4294967295,0),d.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):M(this,e,t,!0),t+4},d.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,4294967295,0),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},d.prototype.writeIntLE=function(e,t,n,a){e=+e,t|=0,a||b(this,e,t,n,(a=Math.pow(2,8*n-1))-1,-a);var r=0,o=1,i=0;for(this[t]=255&e;++r>0)-i&255;return t+n},d.prototype.writeIntBE=function(e,t,n,a){e=+e,t|=0,a||b(this,e,t,n,(a=Math.pow(2,8*n-1))-1,-a);var r=n-1,o=1,i=0;for(this[t+r]=255&e;0<=--r&&(o*=256);)e<0&&0===i&&0!==this[t+r+1]&&(i=1),this[t+r]=(e/o>>0)-i&255;return t+n},d.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,1,127,-128),d.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&(e=e<0?255+e+1:e),t+1},d.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,2,32767,-32768),d.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):w(this,e,t,!0),t+2},d.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,2,32767,-32768),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):w(this,e,t,!1),t+2},d.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,2147483647,-2147483648),d.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):M(this,e,t,!0),t+4},d.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||b(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),d.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):M(this,e,t,!1),t+4},d.prototype.writeFloatLE=function(e,t,n){return x(this,e,t,!0,n)},d.prototype.writeFloatBE=function(e,t,n){return x(this,e,t,!1,n)},d.prototype.writeDoubleLE=function(e,t,n){return C(this,e,t,!0,n)},d.prototype.writeDoubleBE=function(e,t,n){return C(this,e,t,!1,n)},d.prototype.copy=function(e,t,n,a){if(n=n||0,a||0===a||(a=this.length),t>=e.length&&(t=e.length),(a=0=this.length)throw new RangeError("sourceStart out of bounds");if(a<0)throw new RangeError("sourceEnd out of bounds");a>this.length&&(a=this.length);var r,o=(a=e.length-t>>=0,n=void 0===n?this.length:n>>>0,"number"==typeof(e=e||0))for(s=t;s>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function O(e){return S.toByteArray(function(e){var t;if((e=((t=e).trim?t.trim():t.replace(/^\s+|\s+$/g,"")).replace(T,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function D(e,t,n,a){for(var r=0;r=t.length||r>=e.length);++r)t[r+n]=e[r];return r}}.call(this,P(65))},function(e,t,n){"use strict";var o=n(138);function i(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,a=this._readableState&&this._readableState.destroyed,r=this._writableState&&this._writableState.destroyed;return a||r?t?t(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,o.nextTick(i,this,e)):o.nextTick(i,this,e)):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?n._writableState?n._writableState.errorEmitted||(n._writableState.errorEmitted=!0,o.nextTick(i,n,e)):o.nextTick(i,n,e):t&&t(e)})),this},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";var a=n(139).Buffer,r=a.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function o(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"==typeof t||a.isEncoding!==r&&r(e))return t||e;throw new Error("Unknown encoding: "+e)}function i(e){var t;switch(this.encoding=o(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=l,t=4;break;case"base64":this.text=d,this.end=f,t=3;break;default:return this.write=p,void(this.end=h)}this.lastNeed=0,this.lastTotal=0,this.lastChar=a.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function l(e){var t,n=this.lastTotal-this.lastNeed,a=(t=this,128!=(192&(a=e)[0])?(t.lastNeed=0,"�"):1e.slidesToShow&&(n=e.slideWidth*e.slidesToShow*-1,o=e.slideHeight*e.slidesToShow*-1),e.slideCount%e.slidesToScroll!=0&&(t=e.slideIndex+e.slidesToScroll>e.slideCount&&e.slideCount>e.slidesToShow,t=e.rtl?(e.slideIndex>=e.slideCount?e.slideCount-e.slideIndex:e.slideIndex)+e.slidesToScroll>e.slideCount&&e.slideCount>e.slidesToShow:t)&&(o=e.slideIndex>e.slideCount?(n=(e.slidesToShow-(e.slideIndex-e.slideCount))*e.slideWidth*-1,(e.slidesToShow-(e.slideIndex-e.slideCount))*e.slideHeight*-1):(n=e.slideCount%e.slidesToScroll*e.slideWidth*-1,e.slideCount%e.slidesToScroll*e.slideHeight*-1))):e.slideCount%e.slidesToScroll!=0&&e.slideIndex+e.slidesToScroll>e.slideCount&&e.slideCount>e.slidesToShow&&(n=(e.slidesToShow-e.slideCount%e.slidesToScroll)*e.slideWidth),e.centerMode&&(e.infinite?n+=e.slideWidth*Math.floor(e.slidesToShow/2):n=e.slideWidth*Math.floor(e.slidesToShow/2)),a=e.vertical?e.slideIndex*e.slideHeight*-1+o:e.slideIndex*e.slideWidth*-1+n,!0===e.variableWidth&&(t=void 0,a=(r=e.slideCount<=e.slidesToShow||!1===e.infinite?i.default.findDOMNode(e.trackRef).childNodes[e.slideIndex]:(t=e.slideIndex+e.slidesToShow,i.default.findDOMNode(e.trackRef).childNodes[t]))?-1*r.offsetLeft:0,!0===e.centerMode)&&(r=!1===e.infinite?i.default.findDOMNode(e.trackRef).children[e.slideIndex]:i.default.findDOMNode(e.trackRef).children[e.slideIndex+e.slidesToShow+1])?-1*r.offsetLeft+(e.listWidth-r.offsetWidth)/2:a)}},function(e,t,n){"use strict";t.__esModule=!0;var p=u(n(3)),h=u(n(17)),o=u(n(4)),i=u(n(7)),a=u(n(8)),m=u(n(0)),r=u(n(5)),g=u(n(19)),s=u(n(6)),y=u(n(26)),l=n(11);function u(e){return e&&e.__esModule?e:{default:e}}c=m.default.Component,(0,a.default)(d,c),d.prototype.render=function(){var e=this.props,t=e.title,n=e.children,a=e.className,r=e.isExpanded,o=e.disabled,i=e.style,s=e.prefix,l=e.onClick,u=e.id,e=(0,h.default)(e,["title","children","className","isExpanded","disabled","style","prefix","onClick","id"]),a=(0,g.default)(((c={})[s+"collapse-panel"]=!0,c[s+"collapse-panel-hidden"]=!r,c[s+"collapse-panel-expanded"]=r,c[s+"collapse-panel-disabled"]=o,c[a]=a,c)),c=(0,g.default)(((c={})[s+"collapse-panel-icon"]=!0,c[s+"collapse-panel-icon-expanded"]=r,c)),d=u?u+"-heading":void 0,f=u?u+"-region":void 0;return m.default.createElement("div",(0,p.default)({className:a,style:i,id:u},e),m.default.createElement("div",{id:d,className:s+"collapse-panel-title",onClick:l,onKeyDown:this.onKeyDown,tabIndex:"0","aria-disabled":o,"aria-expanded":r,"aria-controls":f,role:"button"},m.default.createElement(y.default,{type:"arrow-right",className:c,"aria-hidden":"true"}),t),m.default.createElement("div",{className:s+"collapse-panel-content",role:"region",id:f},n))},a=n=d,n.propTypes={prefix:r.default.string,style:r.default.object,children:r.default.any,isExpanded:r.default.bool,disabled:r.default.bool,title:r.default.node,className:r.default.string,onClick:r.default.func,id:r.default.string},n.defaultProps={prefix:"next-",isExpanded:!1,onClick:l.func.noop},n.isNextPanel=!0;var c,r=a;function d(){var e,n;(0,o.default)(this,d);for(var t=arguments.length,a=Array(t),r=0;r\n com.alibaba.nacos\n nacos-client\n ${version}\n \n*/\npackage com.alibaba.nacos.example;\n\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * Config service example\n *\n * @author Nacos\n *\n */\npublic class ConfigExample {\n\n\tpublic static void main(String[] args) throws NacosException, InterruptedException {\n\t\tString serverAddr = "localhost";\n\t\tString dataId = "'.concat(e.dataId,'";\n\t\tString group = "').concat(e.group,'";\n\t\tProperties properties = new Properties();\n\t\tproperties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);\n\t\tConfigService configService = NacosFactory.createConfigService(properties);\n\t\tString content = configService.getConfig(dataId, group, 5000);\n\t\tSystem.out.println(content);\n\t\tconfigService.addListener(dataId, group, new Listener() {\n\t\t\t@Override\n\t\t\tpublic void receiveConfigInfo(String configInfo) {\n\t\t\t\tSystem.out.println("receive:" + configInfo);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic Executor getExecutor() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t});\n\n\t\tboolean isPublishOk = configService.publishConfig(dataId, group, "content");\n\t\tSystem.out.println(isPublishOk);\n\n\t\tThread.sleep(3000);\n\t\tcontent = configService.getConfig(dataId, group, 5000);\n\t\tSystem.out.println(content);\n\n\t\tboolean isRemoveOk = configService.removeConfig(dataId, group);\n\t\tSystem.out.println(isRemoveOk);\n\t\tThread.sleep(3000);\n\n\t\tcontent = configService.getConfig(dataId, group, 5000);\n\t\tSystem.out.println(content);\n\t\tThread.sleep(300000);\n\n\t}\n}\n')}},{key:"getNodejsCode",value:function(e){return"TODO"}},{key:"getCppCode",value:function(e){return"TODO"}},{key:"getShellCode",value:function(e){return"TODO"}},{key:"getPythonCode",value:function(e){return'/*\n* Demo for Nacos\n*/\nimport json\nimport socket\n\nimport nacos\n\n\ndef get_host_ip():\n res = socket.gethostbyname(socket.gethostname())\n return res\n\n\ndef load_config(content):\n _config = json.loads(content)\n return _config\n\n\ndef nacos_config_callback(args):\n content = args[\'raw_content\']\n load_config(content)\n\n\nclass NacosClient:\n service_name = None\n service_port = None\n service_group = None\n\n def __init__(self, server_endpoint, namespace_id, username=None, password=None):\n self.client = nacos.NacosClient(server_endpoint,\n namespace=namespace_id,\n username=username,\n password=password)\n self.endpoint = server_endpoint\n self.service_ip = get_host_ip()\n\n def register(self):\n self.client.add_naming_instance(self.service_name,\n self.service_ip,\n self.service_port,\n group_name=self.service_group)\n\n def modify(self, service_name, service_ip=None, service_port=None):\n self.client.modify_naming_instance(service_name,\n service_ip if service_ip else self.service_ip,\n service_port if service_port else self.service_port)\n\n def unregister(self):\n self.client.remove_naming_instance(self.service_name,\n self.service_ip,\n self.service_port)\n\n def set_service(self, service_name, service_ip, service_port, service_group):\n self.service_name = service_name\n self.service_ip = service_ip\n self.service_port = service_port\n self.service_group = service_group\n\n async def beat_callback(self):\n self.client.send_heartbeat(self.service_name,\n self.service_ip,\n self.service_port)\n\n def load_conf(self, data_id, group):\n return self.client.get_config(data_id=data_id, group=group, no_snapshot=True)\n\n def add_conf_watcher(self, data_id, group, callback):\n self.client.add_config_watcher(data_id=data_id, group=group, cb=callback)\n\n\nif __name__ == \'__main__\':\n nacos_config = {\n "nacos_data_id":"test",\n "nacos_server_ip":"127.0.0.1",\n "nacos_namespace":"public",\n "nacos_groupName":"DEFAULT_GROUP",\n "nacos_user":"nacos",\n "nacos_password":"1234567"\n }\n nacos_data_id = nacos_config["nacos_data_id"]\n SERVER_ADDRESSES = nacos_config["nacos_server_ip"]\n NAMESPACE = nacos_config["nacos_namespace"]\n groupName = nacos_config["nacos_groupName"]\n user = nacos_config["nacos_user"]\n password = nacos_config["nacos_password"]\n # todo 将另一个路由对象(通常定义在其他模块或文件中)合并到主应用(app)中。\n # app.include_router(custom_api.router, tags=[\'test\'])\n service_ip = get_host_ip()\n client = NacosClient(SERVER_ADDRESSES, NAMESPACE, user, password)\n client.add_conf_watcher(nacos_data_id, groupName, nacos_config_callback)\n\n # 启动时,强制同步一次配置\n data_stream = client.load_conf(nacos_data_id, groupName)\n json_config = load_config(data_stream)\n'}},{key:"getCSharpCode",value:function(e){return'/*\nDemo for Basic Nacos Opreation\nApp.csproj\n\n\n \n\n*/\n\nusing Microsoft.Extensions.DependencyInjection;\nusing Nacos.V2;\nusing Nacos.V2.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n string serverAddr = "http://localhost:8848";\n string dataId = "'.concat(e.dataId,'";\n string group = "').concat(e.group,'";\n\n IServiceCollection services = new ServiceCollection();\n\n services.AddNacosV2Config(x =>\n {\n x.ServerAddresses = new List { serverAddr };\n x.Namespace = "cs-test";\n\n // swich to use http or rpc\n x.ConfigUseRpc = true;\n });\n\n IServiceProvider serviceProvider = services.BuildServiceProvider();\n var configSvc = serviceProvider.GetService();\n\n var content = await configSvc.GetConfig(dataId, group, 3000);\n Console.WriteLine(content);\n\n var listener = new ConfigListener();\n\n await configSvc.AddListener(dataId, group, listener);\n\n var isPublishOk = await configSvc.PublishConfig(dataId, group, "content");\n Console.WriteLine(isPublishOk);\n\n await Task.Delay(3000);\n content = await configSvc.GetConfig(dataId, group, 5000);\n Console.WriteLine(content);\n\n var isRemoveOk = await configSvc.RemoveConfig(dataId, group);\n Console.WriteLine(isRemoveOk);\n await Task.Delay(3000);\n\n content = await configSvc.GetConfig(dataId, group, 5000);\n Console.WriteLine(content);\n await Task.Delay(300000);\n }\n\n internal class ConfigListener : IListener\n {\n public void ReceiveConfigInfo(string configInfo)\n {\n Console.WriteLine("receive:" + configInfo);\n }\n }\n}\n\n/*\nRefer to document: https://github.com/nacos-group/nacos-sdk-csharp/tree/dev/samples/MsConfigApp\nDemo for ASP.NET Core Integration\nMsConfigApp.csproj\n\n\n \n\n*/\n\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Hosting;\nusing Serilog;\nusing Serilog.Events;\n\npublic class Program\n{\n public static void Main(string[] args)\n {\n Log.Logger = new LoggerConfiguration()\n .Enrich.FromLogContext()\n .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)\n .MinimumLevel.Override("System", LogEventLevel.Warning)\n .MinimumLevel.Debug()\n .WriteTo.Console()\n .CreateLogger();\n\n try\n {\n Log.ForContext().Information("Application starting...");\n CreateHostBuilder(args, Log.Logger).Build().Run();\n }\n catch (System.Exception ex)\n {\n Log.ForContext().Fatal(ex, "Application start-up failed!!");\n }\n finally\n {\n Log.CloseAndFlush();\n }\n }\n\n public static IHostBuilder CreateHostBuilder(string[] args, Serilog.ILogger logger) =>\n Host.CreateDefaultBuilder(args)\n .ConfigureAppConfiguration((context, builder) =>\n {\n var c = builder.Build();\n builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), logAction: x => x.AddSerilog(logger));\n })\n .ConfigureWebHostDefaults(webBuilder =>\n {\n webBuilder.UseStartup().UseUrls("http://*:8787");\n })\n .UseSerilog();\n}\n ')}},{key:"openDialog",value:function(e){var t=this;this.setState({dialogvisible:!0}),this.record=e,setTimeout(function(){t.getData()})}},{key:"closeDialog",value:function(){this.setState({dialogvisible:!1})}},{key:"createCodeMirror",value:function(e,t){var n=this.refs.codepreview;n&&(n.innerHTML="",this.cm=window.CodeMirror(n,{value:t,mode:e,height:400,width:500,lineNumbers:!0,theme:"xq-light",lint:!0,tabMode:"indent",autoMatchParens:!0,textWrapping:!0,gutters:["CodeMirror-lint-markers"],extraKeys:{F1:function(e){e.setOption("fullScreen",!e.getOption("fullScreen"))},Esc:function(e){e.getOption("fullScreen")&&e.setOption("fullScreen",!1)}}}))}},{key:"changeTab",value:function(e,t){var n=this;setTimeout(function(){n[e]=!0,n.createCodeMirror("text/javascript",t)})}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e;return x.a.createElement("div",null,x.a.createElement(y.a,{title:e.sampleCode,style:{width:"80%"},visible:this.state.dialogvisible,footer:x.a.createElement("div",null),onClose:this.closeDialog.bind(this)},x.a.createElement("div",{style:{height:500}},x.a.createElement(H.a,{tip:e.loading,style:{width:"100%"},visible:this.state.loading},x.a.createElement(L.a,{shape:"text",style:{height:40,paddingBottom:10}},x.a.createElement(O,{title:"Java",key:1,onClick:this.changeTab.bind(this,"commoneditor1",this.defaultCode)}),x.a.createElement(O,{title:"Spring Boot",key:2,onClick:this.changeTab.bind(this,"commoneditor2",this.sprigboot_code)}),x.a.createElement(O,{title:"Spring Cloud",key:21,onClick:this.changeTab.bind(this,"commoneditor21",this.sprigcloud_code)}),x.a.createElement(O,{title:"Node.js",key:3,onClick:this.changeTab.bind(this,"commoneditor3",this.nodejsCode)}),x.a.createElement(O,{title:"C++",key:4,onClick:this.changeTab.bind(this,"commoneditor4",this.cppCode)}),x.a.createElement(O,{title:"Shell",key:5,onClick:this.changeTab.bind(this,"commoneditor5",this.shellCode)}),x.a.createElement(O,{title:"Python",key:6,onClick:this.changeTab.bind(this,"commoneditor6",this.pythonCode)}),x.a.createElement(O,{title:"C#",key:7,onClick:this.changeTab.bind(this,"commoneditor7",this.csharpCode)})),x.a.createElement("div",{ref:"codepreview"})))))}}]),n}(x.a.Component)).displayName="ShowCodeing",S=S))||S,S=(t(69),t(40)),S=t.n(S),z=(t(756),S.a.Row),D=S.a.Col,W=(0,n.a.config)(((S=function(e){Object(M.a)(n,e);var t=Object(k.a)(n);function n(e){return Object(_.a)(this,n),(e=t.call(this,e)).state={visible:!1,title:"",content:"",isok:!0,dataId:"",group:""},e}return Object(b.a)(n,[{key:"componentDidMount",value:function(){this.initData()}},{key:"initData",value:function(){var e=this.props.locale;this.setState({title:(void 0===e?{}:e).confManagement})}},{key:"openDialog",value:function(e){this.setState({visible:!0,title:e.title,content:e.content,isok:e.isok,dataId:e.dataId,group:e.group,message:e.message})}},{key:"closeDialog",value:function(){this.setState({visible:!1})}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e,t=x.a.createElement("div",{style:{textAlign:"right"}},x.a.createElement(c.a,{type:"primary",onClick:this.closeDialog.bind(this)},e.determine));return x.a.createElement("div",null,x.a.createElement(y.a,{visible:this.state.visible,footer:t,style:{width:555},onCancel:this.closeDialog.bind(this),onClose:this.closeDialog.bind(this),title:e.deletetitle},x.a.createElement("div",null,x.a.createElement(z,null,x.a.createElement(D,{span:"4",style:{paddingTop:16}},x.a.createElement(m.a,{type:"".concat(this.state.isok?"success":"delete","-filling"),style:{color:this.state.isok?"green":"red"},size:"xl"})),x.a.createElement(D,{span:"20"},x.a.createElement("div",null,x.a.createElement("h3",null,this.state.isok?e.deletedSuccessfully:e.deleteFailed),x.a.createElement("p",null,x.a.createElement("span",{style:{color:"#999",marginRight:5}},"Data ID"),x.a.createElement("span",{style:{color:"#c7254e"}},this.state.dataId)),x.a.createElement("p",null,x.a.createElement("span",{style:{color:"#999",marginRight:5}},"Group"),x.a.createElement("span",{style:{color:"#c7254e"}},this.state.group)),this.state.isok?"":x.a.createElement("p",{style:{color:"red"}},this.state.message)))))))}}]),n}(x.a.Component)).displayName="DeleteDialog",S=S))||S,S=(t(757),t(436)),B=t.n(S),U=(0,n.a.config)(((S=function(e){Object(M.a)(n,e);var t=Object(k.a)(n);function n(){return Object(_.a)(this,n),t.apply(this,arguments)}return Object(b.a)(n,[{key:"render",value:function(){var e=this.props,t=e.data,t=void 0===t?{}:t,n=e.height,e=e.locale,a=void 0===e?{}:e;return x.a.createElement("div",null,"notice"===t.modeType?x.a.createElement("div",{"data-spm-click":"gostr=/aliyun;locaid=notice"},x.a.createElement(B.a,{style:{marginBottom:1\n com.alibaba.nacos\n nacos-client\n ${latest.version}\n \n*/\npackage com.alibaba.nacos.example;\n\nimport java.util.Properties;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingFactory;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.listener.Event;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\n\n/**\n * @author nkorange\n */\npublic class NamingExample {\n\n public static void main(String[] args) throws NacosException {\n\n Properties properties = new Properties();\n properties.setProperty("serverAddr", System.getProperty("serverAddr"));\n properties.setProperty("namespace", System.getProperty("namespace"));\n\n NamingService naming = NamingFactory.createNamingService(properties);\n\n naming.registerInstance("'.concat(this.record.name,'", "11.11.11.11", 8888, "TEST1");\n\n naming.registerInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n System.out.println(naming.getAllInstances("').concat(this.record.name,'"));\n\n naming.deregisterInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n System.out.println(naming.getAllInstances("').concat(this.record.name,'"));\n\n naming.subscribe("').concat(this.record.name,'", new EventListener() {\n @Override\n public void onEvent(Event event) {\n System.out.println(((NamingEvent)event).getServiceName());\n System.out.println(((NamingEvent)event).getInstances());\n }\n });\n }\n}')}},{key:"getSpringCode",value:function(e){return'/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example\n* pom.xml\n \n com.alibaba.nacos\n nacos-spring-context\n ${latest.version}\n \n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring\npackage com.alibaba.nacos.example.spring;\n\nimport com.alibaba.nacos.api.annotation.NacosProperties;\nimport com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\n@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))\npublic class NacosConfiguration {\n\n}\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring/controller\npackage com.alibaba.nacos.example.spring.controller;\n\nimport com.alibaba.nacos.api.annotation.NacosInjected;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\n\nimport static org.springframework.web.bind.annotation.RequestMethod.GET;\n\n@Controller\n@RequestMapping("discovery")\npublic class DiscoveryController {\n\n @NacosInjected\n private NamingService namingService;\n\n @RequestMapping(value = "/get", method = GET)\n @ResponseBody\n public List get(@RequestParam String serviceName) throws NacosException {\n return namingService.getAllInstances(serviceName);\n }\n}'}},{key:"getSpringBootCode",value:function(e){return'/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example\n* pom.xml\n \n com.alibaba.boot\n nacos-discovery-spring-boot-starter\n ${latest.version}\n \n*/\n/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/resources\n* application.properties\n nacos.discovery.server-addr=127.0.0.1:8848\n*/\n// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/java/com/alibaba/nacos/example/spring/boot/controller\n\npackage com.alibaba.nacos.example.spring.boot.controller;\n\nimport com.alibaba.nacos.api.annotation.NacosInjected;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport java.util.List;\n\nimport static org.springframework.web.bind.annotation.RequestMethod.GET;\n\n@Controller\n@RequestMapping("discovery")\npublic class DiscoveryController {\n\n @NacosInjected\n private NamingService namingService;\n\n @RequestMapping(value = "/get", method = GET)\n @ResponseBody\n public List get(@RequestParam String serviceName) throws NacosException {\n return namingService.getAllInstances(serviceName);\n }\n}'}},{key:"getSpringCloudCode",value:function(e){return"/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/\n* pom.xml\n \n org.springframework.cloud\n spring-cloud-starter-alibaba-nacos-discovery\n ${latest.version}\n \n*/\n\n// nacos-spring-cloud-provider-example\n\n/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/resources\n* application.properties\nserver.port=18080\nspring.application.name=".concat(this.record.name,'\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/java/com/alibaba/nacos/example/spring/cloud\npackage com.alibaba.nacos.example.spring.cloud;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class NacosProviderApplication {\n\n public static void main(String[] args) {\n SpringApplication.run(NacosProviderApplication.class, args);\n}\n\n @RestController\n class EchoController {\n @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)\n public String echo(@PathVariable String string) {\n return "Hello Nacos Discovery " + string;\n }\n }\n}\n\n// nacos-spring-cloud-consumer-example\n\n/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/resources\n* application.properties\nspring.application.name=micro-service-oauth2\nspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848\n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/java/com/alibaba/nacos/example/spring/cloud\npackage com.alibaba.nacos.example.spring.cloud;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalanced;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.client.RestTemplate;\n\n/**\n * @author xiaojing\n */\n@SpringBootApplication\n@EnableDiscoveryClient\npublic class NacosConsumerApplication {\n\n @LoadBalanced\n @Bean\n public RestTemplate restTemplate() {\n return new RestTemplate();\n }\n\n public static void main(String[] args) {\n SpringApplication.run(NacosConsumerApplication.class, args);\n }\n\n @RestController\n public class TestController {\n\n private final RestTemplate restTemplate;\n\n @Autowired\n public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}\n\n @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)\n public String echo(@PathVariable String str) {\n return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);\n }\n }\n}')}},{key:"getNodejsCode",value:function(e){return"TODO"}},{key:"getCppCode",value:function(e){return"TODO"}},{key:"getShellCode",value:function(e){return"TODO"}},{key:"getPythonCode",value:function(e){return'/*\n* Demo for Nacos\n*/\nimport json\nimport socket\n\nimport nacos\n\n\ndef get_host_ip():\n res = socket.gethostbyname(socket.gethostname())\n return res\n\n\ndef load_config(content):\n _config = json.loads(content)\n return _config\n\n\ndef nacos_config_callback(args):\n content = args[\'raw_content\']\n load_config(content)\n\n\nclass NacosClient:\n service_name = None\n service_port = None\n service_group = None\n\n def __init__(self, server_endpoint, namespace_id, username=None, password=None):\n self.client = nacos.NacosClient(server_endpoint,\n namespace=namespace_id,\n username=username,\n password=password)\n self.endpoint = server_endpoint\n self.service_ip = get_host_ip()\n\n def register(self):\n self.client.add_naming_instance(self.service_name,\n self.service_ip,\n self.service_port,\n group_name=self.service_group)\n\n def modify(self, service_name, service_ip=None, service_port=None):\n self.client.modify_naming_instance(service_name,\n service_ip if service_ip else self.service_ip,\n service_port if service_port else self.service_port)\n\n def unregister(self):\n self.client.remove_naming_instance(self.service_name,\n self.service_ip,\n self.service_port)\n\n def set_service(self, service_name, service_ip, service_port, service_group):\n self.service_name = service_name\n self.service_ip = service_ip\n self.service_port = service_port\n self.service_group = service_group\n\n async def beat_callback(self):\n self.client.send_heartbeat(self.service_name,\n self.service_ip,\n self.service_port)\n\n def load_conf(self, data_id, group):\n return self.client.get_config(data_id=data_id, group=group, no_snapshot=True)\n\n def add_conf_watcher(self, data_id, group, callback):\n self.client.add_config_watcher(data_id=data_id, group=group, cb=callback)\n\n\nif __name__ == \'__main__\':\n nacos_config = {\n "nacos_data_id":"test",\n "nacos_server_ip":"127.0.0.1",\n "nacos_namespace":"public",\n "nacos_groupName":"DEFAULT_GROUP",\n "nacos_user":"nacos",\n "nacos_password":"1234567"\n }\n nacos_data_id = nacos_config["nacos_data_id"]\n SERVER_ADDRESSES = nacos_config["nacos_server_ip"]\n NAMESPACE = nacos_config["nacos_namespace"]\n groupName = nacos_config["nacos_groupName"]\n user = nacos_config["nacos_user"]\n password = nacos_config["nacos_password"]\n # todo 将另一个路由对象(通常定义在其他模块或文件中)合并到主应用(app)中。\n # app.include_router(custom_api.router, tags=[\'test\'])\n service_ip = get_host_ip()\n client = NacosClient(SERVER_ADDRESSES, NAMESPACE, user, password)\n client.add_conf_watcher(nacos_data_id, groupName, nacos_config_callback)\n\n # 启动时,强制同步一次配置\n data_stream = client.load_conf(nacos_data_id, groupName)\n json_config = load_config(data_stream)\n #设定服务\n client.set_service(json_config["service_name"], json_config.get("service_ip", service_ip), service_port, groupName)\n #注册服务\n client.register()\n #下线服务\n client.unregister()\n'}},{key:"getCSharpCode",value:function(e){return'/* Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/\nDemo for Basic Nacos Opreation\nApp.csproj\n\n\n \n\n*/\n\nusing Microsoft.Extensions.DependencyInjection;\nusing Nacos.V2;\nusing Nacos.V2.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n IServiceCollection services = new ServiceCollection();\n\n services.AddNacosV2Naming(x =>\n {\n x.ServerAddresses = new List { "http://localhost:8848/" };\n x.Namespace = "cs-test";\n\n // swich to use http or rpc\n x.NamingUseRpc = true;\n });\n\n IServiceProvider serviceProvider = services.BuildServiceProvider();\n var namingSvc = serviceProvider.GetService();\n\n await namingSvc.RegisterInstance("'.concat(this.record.name,'", "11.11.11.11", 8888, "TEST1");\n\n await namingSvc.RegisterInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(await namingSvc.GetAllInstances("').concat(this.record.name,'")));\n\n await namingSvc.DeregisterInstance("').concat(this.record.name,'", "2.2.2.2", 9999, "DEFAULT");\n\n var listener = new EventListener();\n\n await namingSvc.Subscribe("').concat(this.record.name,'", listener);\n }\n\n internal class EventListener : IEventListener\n {\n public Task OnEvent(IEvent @event)\n {\n Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(@event));\n return Task.CompletedTask;\n }\n }\n}\n\n/* Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/\nDemo for ASP.NET Core Integration\nApp.csproj\n\n\n \n\n*/\n\n/* Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/blob/dev/samples/App1/appsettings.json\n* appsettings.json\n{\n "nacos": {\n "ServerAddresses": [ "http://localhost:8848" ],\n "DefaultTimeOut": 15000,\n "Namespace": "cs",\n "ServiceName": "App1",\n "GroupName": "DEFAULT_GROUP",\n "ClusterName": "DEFAULT",\n "Port": 0,\n "Weight": 100,\n "RegisterEnabled": true,\n "InstanceEnabled": true,\n "Ephemeral": true,\n "NamingUseRpc": true,\n "NamingLoadCacheAtStart": ""\n }\n}\n*/\n\n// Refer to document: https://github.com/nacos-group/nacos-sdk-csharp/blob/dev/samples/App1/Startup.cs\nusing Nacos.AspNetCore.V2;\n\npublic class Startup\n{\n public Startup(IConfiguration configuration)\n {\n Configuration = configuration;\n }\n\n public IConfiguration Configuration { get; }\n\n public void ConfigureServices(IServiceCollection services)\n {\n // ....\n services.AddNacosAspNet(Configuration);\n }\n\n public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n {\n // ....\n }\n}\n ')}},{key:"openDialog",value:function(e){var t=this;this.setState({dialogvisible:!0}),this.record=e,setTimeout(function(){t.getData()})}},{key:"closeDialog",value:function(){this.setState({dialogvisible:!1})}},{key:"createCodeMirror",value:function(e,t){var n=this.refs.codepreview;n&&(n.innerHTML="",this.cm=window.CodeMirror(n,{value:t,mode:e,height:400,width:500,lineNumbers:!0,theme:"xq-light",lint:!0,tabMode:"indent",autoMatchParens:!0,textWrapping:!0,gutters:["CodeMirror-lint-markers"],extraKeys:{F1:function(e){e.setOption("fullScreen",!e.getOption("fullScreen"))},Esc:function(e){e.getOption("fullScreen")&&e.setOption("fullScreen",!1)}}}),this.cm.setSize("auto","490px"))}},{key:"changeTab",value:function(e,t){var n=this;setTimeout(function(){n[e]=!0,n.createCodeMirror("text/javascript",t)})}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e;return O.a.createElement("div",null,O.a.createElement(o.a,{title:e.sampleCode,style:{width:"80%"},visible:this.state.dialogvisible,footer:O.a.createElement("div",null),onClose:this.closeDialog.bind(this)},O.a.createElement("div",{style:{height:500}},O.a.createElement(h.a,{tip:e.loading,style:{width:"100%"},visible:this.state.loading},O.a.createElement(m.a,{shape:"text",style:{height:40,paddingBottom:10}},O.a.createElement(g,{title:"Java",key:0,onClick:this.changeTab.bind(this,"commoneditor1",this.defaultCode)}),O.a.createElement(g,{title:"Spring",key:1,onClick:this.changeTab.bind(this,"commoneditor1",this.springCode)}),O.a.createElement(g,{title:"Spring Boot",key:2,onClick:this.changeTab.bind(this,"commoneditor2",this.sprigbootCode)}),O.a.createElement(g,{title:"Spring Cloud",key:21,onClick:this.changeTab.bind(this,"commoneditor21",this.sprigcloudCode)}),O.a.createElement(g,{title:"Node.js",key:3,onClick:this.changeTab.bind(this,"commoneditor3",this.nodejsCode)}),O.a.createElement(g,{title:"C++",key:4,onClick:this.changeTab.bind(this,"commoneditor4",this.cppCode)}),O.a.createElement(g,{title:"Shell",key:5,onClick:this.changeTab.bind(this,"commoneditor5",this.shellCode)}),O.a.createElement(g,{title:"Python",key:6,onClick:this.changeTab.bind(this,"commoneditor6",this.pythonCode)}),O.a.createElement(g,{title:"C#",key:7,onClick:this.changeTab.bind(this,"commoneditor7",this.csharpCode)})),O.a.createElement("div",{ref:"codepreview"})))))}}]),n}(O.a.Component)).displayName="ShowServiceCodeing",f=f))||f,Y=t(51),I=t(146),A=(t(778),t(22)),R=L.a.Item,H=d.a.Row,F=d.a.Col,z=T.a.Column,d=(0,n.a.config)(((f=function(e){Object(u.a)(n,e);var t=Object(c.a)(n);function n(e){var a;return Object(s.a)(this,n),(a=t.call(this,e)).getQueryLater=function(){setTimeout(function(){return a.queryServiceList()})},a.showcode=function(){setTimeout(function(){return a.queryServiceList()})},a.setNowNameSpace=function(e,t,n){return a.setState({nowNamespaceName:e,nowNamespaceId:t,nowNamespaceDesc:n})},a.rowColor=function(e){return{className:e.healthyInstanceCount?"":"row-bg-red"}},a.editServiceDialog=O.a.createRef(),a.showcode=O.a.createRef(),a.state={loading:!1,total:0,pageSize:10,currentPage:1,dataSource:[],search:{serviceName:Object(p.b)("serviceNameParam")||"",groupName:Object(p.b)("groupNameParam")||""},hasIpCount:!("false"===localStorage.getItem("hasIpCount"))},a.field=new i.a(Object(l.a)(a)),a}return Object(a.a)(n,[{key:"openLoading",value:function(){this.setState({loading:!0})}},{key:"closeLoading",value:function(){this.setState({loading:!1})}},{key:"openEditServiceDialog",value:function(){try{this.editServiceDialog.current.getInstance().show(this.state.service)}catch(e){}}},{key:"queryServiceList",value:function(){var n=this,e=this.state,t=e.currentPage,a=e.pageSize,r=e.search,o=e.withInstances,o=void 0!==o&&o,e=e.hasIpCount,e=["hasIpCount=".concat(e),"withInstances=".concat(o),"pageNo=".concat(t),"pageSize=".concat(a),"serviceNameParam=".concat(r.serviceName),"groupNameParam=".concat(r.groupName)];Object(p.f)({serviceNameParam:r.serviceName,groupNameParam:r.groupName}),this.openLoading(),Object(p.e)({url:"v3/console/ns/service/list?".concat(e.join("&")),success:function(e){var e=e.data,e=void 0===e?{}:e,t=e.count,e=e.serviceList;n.setState({dataSource:void 0===e?[]:e,total:void 0===t?0:t,loading:!1})},error:function(){return n.setState({dataSource:[],total:0,currentPage:0,loading:!1})}})}},{key:"showSampleCode",value:function(e){this.showcode.current.getInstance().openDialog(e)}},{key:"querySubscriber",value:function(e){var t=e.name,e=e.groupName,n=this.state.nowNamespaceId;this.props.history.push(Object(D.a)("/subscriberList",{namespace:n,name:t,groupName:e}))}},{key:"handlePageSizeChange",value:function(e){var t=this;this.setState({pageSize:e},function(){return t.queryServiceList()})}},{key:"deleteService",value:function(e){var t=this,n=this.props.locale,n=void 0===n?{}:n,a=n.prompt,n=n.promptDelete;o.a.confirm({title:a,content:n,onOk:function(){Object(p.e)({method:"DELETE",url:"v3/console/ns/service?serviceName=".concat(e.name,"&groupName=").concat(e.groupName),dataType:"json",beforeSend:function(){return t.openLoading()},success:function(e){0!==e.code?r.a.error(e.message||"删除服务失败"):(r.a.success("服务删除成功"),t.queryServiceList())},error:function(e){var t;r.a.error((null==(t=e.data)?void 0:t.responseText)||e.statusText||"请求失败")},complete:function(){return t.closeLoading()}})}})}},{key:"render",value:function(){var a=this,e=this.props.locale,t=void 0===e?{}:e,e=t.pubNoData,n=t.serviceList,r=t.serviceName,o=t.serviceNamePlaceholder,i=t.groupName,s=t.groupNamePlaceholder,l=t.hiddenEmptyService,u=t.query,c=t.create,d=t.operation,f=t.detail,p=t.sampleCode,h=t.deleteAction,m=t.subscriber,g=this.state,y=g.search,v=g.nowNamespaceName,_=g.nowNamespaceId,b=g.nowNamespaceDesc,g=g.hasIpCount,w=this.field,M=w.init,w=w.getValue;return this.init=M,this.getValue=w,O.a.createElement("div",{className:"main-container service-management"},O.a.createElement(Y.a,{title:n,desc:b,namespaceId:_,namespaceName:v,nameSpace:!0}),O.a.createElement(N.a,{setNowNameSpace:this.setNowNameSpace,namespaceCallBack:this.getQueryLater}),O.a.createElement(H,{className:"demo-row",style:{marginBottom:10,padding:0}},O.a.createElement(F,{span:"24"},O.a.createElement(L.a,{inline:!0,field:this.field},O.a.createElement(R,{label:""},O.a.createElement(C.a,{type:"primary",onClick:function(){return a.openEditServiceDialog()}},c)),O.a.createElement(R,{label:r},O.a.createElement(E.a,{placeholder:o,style:{width:200},value:y.serviceName,onChange:function(e){return a.setState({search:Object(x.a)(Object(x.a)({},y),{},{serviceName:e})})},onPressEnter:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})}})),O.a.createElement(R,{label:i},O.a.createElement(E.a,{placeholder:s,style:{width:200},value:y.groupName,onChange:function(e){return a.setState({search:Object(x.a)(Object(x.a)({},y),{},{groupName:e})})},onPressEnter:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})}})),O.a.createElement(L.a.Item,{label:"".concat(l)},O.a.createElement(S.a,{checked:g,onChange:function(e){return a.setState({hasIpCount:e,currentPage:1},function(){localStorage.setItem("hasIpCount",e),a.queryServiceList()})}})),O.a.createElement(R,{label:""},O.a.createElement(C.a,{type:"primary",onClick:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})},style:{marginRight:10}},u))))),O.a.createElement(H,{style:{padding:0}},O.a.createElement(F,{span:"24",style:{padding:0}},O.a.createElement(T.a,{dataSource:this.state.dataSource,locale:{empty:e},rowProps:function(e){return a.rowColor(e)},loading:this.state.loading},O.a.createElement(z,{title:t.columnServiceName,dataIndex:"name"}),O.a.createElement(z,{title:t.groupName,dataIndex:"groupName"}),O.a.createElement(z,{title:t.columnClusterCount,dataIndex:"clusterCount"}),O.a.createElement(z,{title:t.columnIpCount,dataIndex:"ipCount"}),O.a.createElement(z,{title:t.columnHealthyInstanceCount,dataIndex:"healthyInstanceCount"}),O.a.createElement(z,{title:t.columnTriggerFlag,dataIndex:"triggerFlag"}),O.a.createElement(z,{title:d,align:"center",cell:function(e,t,n){return O.a.createElement("div",null,O.a.createElement("a",{onClick:function(){var e=n.name,t=n.groupName;a.props.history.push(Object(D.a)("/serviceDetail",{name:e,groupName:t}))},style:{marginRight:5}},f),O.a.createElement("span",{style:{marginRight:5}},"|"),O.a.createElement("a",{style:{marginRight:5},onClick:function(){return a.showSampleCode(n)}},p),O.a.createElement("span",{style:{marginRight:5}},"|"),O.a.createElement("a",{style:{marginRight:5},onClick:function(){return a.querySubscriber(n)}},m),O.a.createElement("span",{style:{marginRight:5}},"|"),O.a.createElement("a",{onClick:function(){return a.deleteService(n)},style:{marginRight:5}},h))}})))),O.a.createElement("div",{style:{marginTop:10,textAlign:"right"}},O.a.createElement(k.a,{current:this.state.currentPage,pageSizeList:A.f,pageSizePosition:"start",pageSizeSelector:"dropdown",popupProps:{align:"bl tl"},total:this.state.total,pageSize:this.state.pageSize,totalRender:function(e){return O.a.createElement(I.a,{locale:t,total:e})},onPageSizeChange:function(e){return a.handlePageSizeChange(e)},onChange:function(e){return a.setState({currentPage:e},function(){return a.queryServiceList()})}})),O.a.createElement(j,{ref:this.showcode}),O.a.createElement(P.a,{ref:this.editServiceDialog,openLoading:function(){return a.openLoading()},closeLoading:function(){return a.closeLoading()},queryServiceList:function(){return a.setState({currentPage:1},function(){return a.queryServiceList()})}}))}}]),n}(O.a.Component)).displayName="ServiceList",t=f))||t;e.a=d},function(e,t,n){"use strict";n(67);var a=n(46),u=n.n(a),a=(n(35),n(18)),c=n.n(a),a=(n(66),n(21)),d=n.n(a),a=(n(34),n(20)),f=n.n(a),a=(n(93),n(55)),p=n.n(a),a=(n(38),n(2)),h=n.n(a),a=(n(37),n(10)),m=n.n(a),i=n(13),s=n(14),l=n(23),g=n(16),y=n(15),a=(n(27),n(6)),a=n.n(a),r=n(0),v=n.n(r),r=n(30),_=n(45),b=n(53),w=n(32),o=(n(49),n(28)),M=n.n(o),k=(n(168),h.a.Item),S={labelCol:{fixedSpan:4},wrapperCol:{span:19}},E=(0,a.a.config)(((o=function(e){Object(g.a)(o,e);var r=Object(y.a)(o);function o(){var e;Object(i.a)(this,o);for(var t=arguments.length,n=new Array(t),a=0;ao&&v.a.createElement(u.a,{className:"users-pagination",current:i,total:n.totalCount,pageSize:o,onChange:function(e){return t.setState({pageNo:e},function(){return t.getUsers()})}}),v.a.createElement(E,{visible:s,onOk:function(e){return Object(_.c)(e).then(function(e){return t.setState({pageNo:1},function(){return t.getUsers()}),e})},onCancel:function(){return t.colseCreateUser()}}),v.a.createElement(x.a,{visible:l,username:e,onOk:function(e){return Object(_.k)(e).then(function(e){return t.getUsers(),e})},onCancel:function(){return t.setState({passwordResetUser:void 0,passwordResetUserVisible:!1})}}))}}]),n}(v.a.Component)).displayName="UserManagement",n=o))||n)||n;t.a=r},function(e,t,n){"use strict";n(67);var a=n(46),l=n.n(a),a=(n(35),n(18)),u=n.n(a),c=n(32),a=(n(66),n(21)),d=n.n(a),a=(n(34),n(20)),f=n.n(a),a=(n(93),n(55)),p=n.n(a),a=(n(38),n(2)),h=n.n(a),a=(n(37),n(10)),m=n.n(a),i=n(13),s=n(14),g=n(23),y=n(16),v=n(15),a=(n(27),n(6)),a=n.n(a),r=n(0),_=n.n(r),r=n(30),b=n(45),o=n(86),w=n(53),M=(n(49),n(28)),k=n.n(M),M=(n(59),n(29)),S=n.n(M),E=h.a.Item,x=S.a.Option,C={labelCol:{fixedSpan:4},wrapperCol:{span:19}},T=Object(r.b)(function(e){return{namespaces:e.namespace.namespaces}},{getNamespaces:o.b,searchRoles:b.l})(M=(0,a.a.config)(((M=function(e){Object(y.a)(o,e);var r=Object(v.a)(o);function o(){var t;Object(i.a)(this,o);for(var e=arguments.length,n=new Array(e),a=0;ai&&_.a.createElement(l.a,{className:"users-pagination",current:s,total:t.totalCount,pageSize:i,onChange:function(e){return a.setState({pageNo:e},function(){return a.getPermissions()})}}),_.a.createElement(T,{visible:n,onOk:function(e){return Object(b.a)(e).then(function(e){return a.setState({pageNo:1},function(){return a.getPermissions()}),e})},onCancel:function(){return a.colseCreatePermission()}}))}}]),n}(_.a.Component)).displayName="PermissionsManagement",n=M))||n)||n);t.a=r},function(e,t,n){"use strict";n(67);var a=n(46),l=n.n(a),a=(n(35),n(18)),u=n.n(a),a=(n(66),n(21)),c=n.n(a),a=(n(34),n(20)),d=n.n(a),a=(n(93),n(55)),f=n.n(a),a=(n(38),n(2)),p=n.n(a),a=(n(37),n(10)),h=n.n(a),i=n(13),s=n(14),m=n(23),g=n(16),y=n(15),a=(n(27),n(6)),a=n.n(a),r=n(0),v=n.n(r),r=n(30),_=n(45),b=n(53),o=(n(59),n(29)),w=n.n(o),o=(n(49),n(28)),M=n.n(o),k=p.a.Item,S={labelCol:{fixedSpan:4},wrapperCol:{span:19}},E=Object(r.b)(function(e){return{users:e.authority.users}},{searchUsers:_.m})(o=(0,a.a.config)(((o=function(e){Object(g.a)(o,e);var r=Object(y.a)(o);function o(){var t;Object(i.a)(this,o);for(var e=arguments.length,n=new Array(e),a=0;ao&&v.a.createElement(l.a,{className:"users-pagination",current:i,total:t.totalCount,pageSize:o,onChange:function(e){return a.setState({pageNo:e},function(){return a.getRoles()})}}),v.a.createElement(E,{visible:s,onOk:function(e){return Object(_.b)(e).then(function(e){return a.getRoles(),e})},onCancel:function(){return a.colseCreateRole()}}))}}]),n}(v.a.Component)).displayName="RolesManagement",n=o))||n)||n);t.a=r},function(e,t,n){"use strict";n(35);function l(e){var t=void 0===(t=localStorage.token)?"{}":t,t=(Object(_.c)(t)&&JSON.parse(t)||{}).globalAdmin,n=[];return"naming"===e?n.push(b):"config"===e?n.push(w):n.push(w,b),t&&n.push(M),n.push(k),n.push(S),n.push(E),n.filter(function(e){return e})}var a=n(18),u=n.n(a),a=(n(47),n(24)),c=n.n(a),a=(n(43),n(26)),d=n.n(a),r=n(13),o=n(14),i=n(16),s=n(15),a=(n(27),n(6)),a=n.n(a),f=n(12),p=(n(84),n(50)),h=n.n(p),p=n(0),m=n.n(p),p=n(39),g=n(30),y=n(108),v=n(52),_=n(48),b={key:"serviceManagementVirtual",children:[{key:"serviceManagement",url:"/serviceManagement"},{key:"subscriberList",url:"/subscriberList"}]},w={key:"configurationManagementVirtual",children:[{key:"configurationManagement",url:"/configurationManagement"},{key:"historyRollback",url:"/historyRollback"},{key:"listeningToQuery",url:"/listeningToQuery"}]},M={key:"authorityControl",children:[{key:"userList",url:"/userManagement"},{key:"roleManagement",url:"/rolesManagement"},{key:"privilegeManagement",url:"/permissionsManagement"}]},k={key:"namespace",url:"/namespace"},S={key:"clusterManagementVirtual",children:[{key:"clusterManagement",url:"/clusterManagement"}]},E={key:"settingCenter",url:"/settingCenter"},x=(n(386),h.a.SubMenu),C=h.a.Item,p=(n=Object(g.b)(function(e){return Object(f.a)(Object(f.a)({},e.locale),e.base)},{getState:v.e,getNotice:v.d,getGuide:v.c}),g=a.a.config,Object(p.g)(a=n(a=g(((v=function(e){Object(i.a)(n,e);var t=Object(s.a)(n);function n(e){return Object(r.a)(this,n),(e=t.call(this,e)).state={visible:!0},e}return Object(o.a)(n,[{key:"componentDidMount",value:function(){this.props.getState(),this.props.getNotice(),this.props.getGuide()}},{key:"goBack",value:function(){this.props.history.goBack()}},{key:"navTo",value:function(e){var t=this.props.location.search,t=new URLSearchParams(t);t.set("namespace",window.nownamespace),t.set("namespaceShowName",window.namespaceShowName),this.props.history.push([e,"?",t.toString()].join(""))}},{key:"isCurrentPath",value:function(e){return e===this.props.location.pathname?"current-path next-selected":void 0}},{key:"defaultOpenKeys",value:function(){for(var t=this,e=l(this.props.functionMode),n=0,a=e.length;nthis.state.pageSize&&S.a.createElement("div",{style:{marginTop:10,textAlign:"right"}},S.a.createElement(v.a,{current:this.state.pageNo,total:a,pageSize:this.state.pageSize,onChange:function(e){return t.setState({pageNo:e},function(){return t.querySubscriberList()})}}))))}}]),n}(S.a.Component)).displayName="SubscriberList",d=n))||d)||d;t.a=f},function(e,t,n){"use strict";n(54);var a=n(36),c=n.n(a),a=(n(67),n(46)),d=n.n(a),a=(n(179),n(78)),f=n.n(a),a=(n(37),n(10)),p=n.n(a),a=(n(34),n(20)),h=n.n(a),a=(n(35),n(18)),r=n.n(a),a=(n(47),n(24)),o=n.n(a),a=(n(49),n(28)),i=n.n(a),s=n(13),l=n(14),u=n(23),m=n(16),g=n(15),a=(n(27),n(6)),a=n.n(a),y=(n(421),n(123)),v=n.n(y),y=(n(66),n(21)),_=n.n(y),y=(n(69),n(40)),y=n.n(y),b=(n(38),n(2)),w=n.n(b),b=n(0),M=n.n(b),k=n(1),b=n(144),S=n.n(b),E=n(51),x=(n(781),w.a.Item),C=y.a.Row,T=y.a.Col,L=_.a.Column,O=v.a.Panel,y=(0,a.a.config)(((b=function(e){Object(m.a)(a,e);var t=Object(g.a)(a);function a(e){var n;return Object(s.a)(this,a),(n=t.call(this,e)).getQueryLater=function(){setTimeout(function(){return n.queryClusterStateList()})},n.setNowNameSpace=function(e,t){return n.setState({nowNamespaceName:e,nowNamespaceId:t})},n.rowColor=function(e){return{className:(e.voteFor,"")}},n.state={loading:!1,total:0,pageSize:10,currentPage:1,keyword:"",dataSource:[]},n.field=new i.a(Object(u.a)(n)),n}return Object(l.a)(a,[{key:"componentDidMount",value:function(){this.getQueryLater()}},{key:"openLoading",value:function(){this.setState({loading:!0})}},{key:"closeLoading",value:function(){this.setState({loading:!1})}},{key:"queryClusterStateList",value:function(){var n=this,e=this.state,t=e.currentPage,a=e.pageSize,r=e.keyword,e=e.withInstances,e=["withInstances=".concat(void 0!==e&&e),"pageNo=".concat(t),"pageSize=".concat(a),"keyword=".concat(r)];Object(k.e)({url:"v3/console/core/cluster/nodes?".concat(e.join("&")),beforeSend:function(){return n.openLoading()},success:function(){var e=0this.state.pageSize&&M.a.createElement("div",{style:{marginTop:10,textAlign:"right"}},M.a.createElement(d.a,{current:this.state.currentPage,total:this.state.total,pageSize:this.state.pageSize,onChange:function(e){return t.setState({currentPage:e},function(){return t.queryClusterStateList()})}}))))}}]),a}(M.a.Component)).displayName="ClusterNodeList",n=b))||n;t.a=y},function(e,t,n){"use strict";n(34);var a=n(20),i=n.n(a),s=n(13),l=n(14),u=n(16),c=n(15),a=(n(27),n(6)),a=n.n(a),r=n(12),o=(n(114),n(75)),o=n.n(o),d=n(0),f=n.n(d),p=(n(784),n(51)),d=n(87),h=n(148),m=n(149),g=n(30),y=n(22),v=o.a.Group,g=Object(g.b)(function(e){return Object(r.a)({},e.locale)},{changeLanguage:d.a,changeTheme:h.a,changeNameShow:m.a})(o=(0,a.a.config)(((n=function(e){Object(u.a)(o,e);var r=Object(c.a)(o);function o(e){Object(s.a)(this,o),e=r.call(this,e);var t=localStorage.getItem(y.p),n=localStorage.getItem(y.j),a=localStorage.getItem(y.g);return e.state={theme:"dark"===t?"dark":"light",language:"en-US"===a?"en-US":"zh-CN",nameShow:"select"===n?"select":"label"},e}return Object(l.a)(o,[{key:"newTheme",value:function(e){this.setState({theme:e})}},{key:"newLanguage",value:function(e){this.setState({language:e})}},{key:"newNameShow",value:function(e){this.setState({nameShow:e})}},{key:"submit",value:function(){var e=this.props,t=e.changeLanguage,n=e.changeTheme,e=e.changeNameShow,a=this.state.language,r=this.state.theme,o=this.state.nameShow;t(a),n(r),e(o)}},{key:"render",value:function(){var e=this.props.locale,e=void 0===e?{}:e,t=[{value:"light",label:e.settingLight},{value:"dark",label:e.settingDark}],n=[{value:"select",label:e.settingShowSelect},{value:"label",label:e.settingShowLabel}];return f.a.createElement(f.a.Fragment,null,f.a.createElement(p.a,{title:e.settingTitle}),f.a.createElement("div",{className:"setting-box"},f.a.createElement("div",{className:"text-box"},f.a.createElement("div",{className:"setting-checkbox"},f.a.createElement("div",{className:"setting-span"},e.settingTheme),f.a.createElement(v,{dataSource:t,value:this.state.theme,onChange:this.newTheme.bind(this)})),f.a.createElement("div",{className:"setting-checkbox"},f.a.createElement("div",{className:"setting-span"},e.settingLocale),f.a.createElement(v,{dataSource:[{value:"en-US",label:"English"},{value:"zh-CN",label:"中文"}],value:this.state.language,onChange:this.newLanguage.bind(this)})),f.a.createElement("div",{className:"setting-checkbox"},f.a.createElement("div",{className:"setting-span"},e.settingShow),f.a.createElement(v,{dataSource:n,value:this.state.nameShow,onChange:this.newNameShow.bind(this)}))),f.a.createElement(i.a,{type:"primary",onClick:this.submit.bind(this)},e.settingSubmit)))}}]),o}(f.a.Component)).displayName="SettingCenter",o=n))||o)||o;t.a=g},function(e,t,V){"use strict";V.r(t),function(e){V(54);var t=V(36),a=V.n(t),t=(V(27),V(6)),r=V.n(t),o=V(13),i=V(14),s=V(16),l=V(15),n=V(12),t=V(0),u=V.n(t),t=V(25),t=V.n(t),c=V(125),d=V(429),f=V(440),p=V(30),h=V(39),m=V(73),g=(V(477),V(449)),y=V(22),v=V(450),_=V(451),b=V(443),w=V(452),M=V(453),k=V(444),S=V(454),E=V(455),x=V(456),C=V(457),T=V(458),L=V(441),O=V(445),D=V(442),N=V(459),P=V(460),j=V(446),I=V(447),A=V(448),R=V(438),H=V(461),Y=V(439),F=V(87),z=V(52),W=V(148),B=V(149),e=(V(785),e.hot,localStorage.getItem(y.g)||localStorage.setItem(y.g,"zh-CN"===navigator.language?"zh-CN":"en-US"),Object(c.b)(Object(n.a)(Object(n.a)({},Y.a),{},{routing:d.routerReducer}))),Y=Object(c.d)(e,Object(c.c)(Object(c.a)(f.a),window[y.l]?window[y.l]():function(e){return e})),U=[{path:"/",exact:!0,render:function(){return u.a.createElement(h.a,{to:"/welcome"})}},{path:"/welcome",component:R.a},{path:"/namespace",component:b.a},{path:"/newconfig",component:w.a},{path:"/configsync",component:M.a},{path:"/configdetail",component:k.a},{path:"/configeditor",component:S.a},{path:"/historyDetail",component:E.a},{path:"/configRollback",component:x.a},{path:"/historyRollback",component:C.a},{path:"/listeningToQuery",component:T.a},{path:"/configurationManagement",component:L.a},{path:"/serviceManagement",component:O.a},{path:"/serviceDetail",component:D.a},{path:"/subscriberList",component:N.a},{path:"/clusterManagement",component:P.a},{path:"/userManagement",component:j.a},{path:"/rolesManagement",component:A.a},{path:"/permissionsManagement",component:I.a},{path:"/settingCenter",component:H.a}],e=Object(p.b)(function(e){return Object(n.a)(Object(n.a)({},e.locale),e.base)},{changeLanguage:F.a,getState:z.e,changeTheme:W.a,changeNameShow:B.a})(d=function(e){Object(s.a)(n,e);var t=Object(l.a)(n);function n(e){return Object(o.a)(this,n),(e=t.call(this,e)).state={shownotice:"none",noticecontent:"",nacosLoading:{}},e}return Object(i.a)(n,[{key:"componentDidMount",value:function(){this.props.getState();var e=localStorage.getItem(y.g),t=localStorage.getItem(y.p),n=localStorage.getItem(y.j);this.props.changeLanguage(e),this.props.changeTheme(t),this.props.changeNameShow(n)}},{key:"router",get:function(){var e=this.props,t=e.loginPageEnabled,e=e.consoleUiEnable;return u.a.createElement(m.a,null,u.a.createElement(h.d,null,t&&"false"===t?null:u.a.createElement(h.b,{path:"/login",component:v.a}),u.a.createElement(h.b,{path:"/register",component:_.a}),u.a.createElement(g.a,null,e&&"true"===e&&U.map(function(e){return u.a.createElement(h.b,Object.assign({key:e.path},e))}))))}},{key:"render",value:function(){var e=this.props,t=e.locale,e=e.loginPageEnabled;return u.a.createElement(a.a,Object.assign({className:"nacos-loading",shape:"flower",tip:"loading...",visible:!e,fullScreen:!0},this.state.nacosLoading),u.a.createElement(r.a,{locale:t},this.router))}}]),n}(u.a.Component))||d;t.a.render(u.a.createElement(p.a,{store:Y},u.a.createElement(e,null)),document.getElementById("root"))}.call(this,V(463)(e))},function(e,t){e.exports=function(e){var t;return e.webpackPolyfill||((t=Object.create(e)).children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),Object.defineProperty(t,"exports",{enumerable:!0}),t.webpackPolyfill=1),t}},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(I,e,t){"use strict"; /** @license React v16.14.0 * react.production.min.js * @@ -335,6 +335,6 @@ var S=P(706),o=P(707),s=P(708);function n(){return d.TYPED_ARRAY_SUPPORT?2147483 * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var a=60103,r=60106,o=60107,i=60108,s=60114,l=60109,u=60110,c=60112,d=60113,f=60120,p=60115,h=60116,m=60121,g=60122,y=60117,v=60129,_=60131;function b(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case a:switch(e=e.type){case o:case s:case i:case d:case f:return e;default:switch(e=e&&e.$$typeof){case u:case c:case h:case p:case l:return e;default:return t}}case r:return t}}}"function"==typeof Symbol&&Symbol.for&&(a=(w=Symbol.for)("react.element"),r=w("react.portal"),o=w("react.fragment"),i=w("react.strict_mode"),s=w("react.profiler"),l=w("react.provider"),u=w("react.context"),c=w("react.forward_ref"),d=w("react.suspense"),f=w("react.suspense_list"),p=w("react.memo"),h=w("react.lazy"),m=w("react.block"),g=w("react.server.block"),y=w("react.fundamental"),v=w("react.debug_trace_mode"),_=w("react.legacy_hidden"));var w=l,M=a,k=c,S=o,E=h,x=p,C=r,T=s,L=i,O=d;t.ContextConsumer=u,t.ContextProvider=w,t.Element=M,t.ForwardRef=k,t.Fragment=S,t.Lazy=E,t.Memo=x,t.Portal=C,t.Profiler=T,t.StrictMode=L,t.Suspense=O,t.isAsyncMode=function(){return!1},t.isConcurrentMode=function(){return!1},t.isContextConsumer=function(e){return b(e)===u},t.isContextProvider=function(e){return b(e)===l},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===a},t.isForwardRef=function(e){return b(e)===c},t.isFragment=function(e){return b(e)===o},t.isLazy=function(e){return b(e)===h},t.isMemo=function(e){return b(e)===p},t.isPortal=function(e){return b(e)===r},t.isProfiler=function(e){return b(e)===s},t.isStrictMode=function(e){return b(e)===i},t.isSuspense=function(e){return b(e)===d},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===s||e===v||e===i||e===d||e===f||e===_||"object"==typeof e&&null!==e&&(e.$$typeof===h||e.$$typeof===p||e.$$typeof===l||e.$$typeof===u||e.$$typeof===c||e.$$typeof===y||e.$$typeof===m||e[0]===g)},t.typeOf=b},function(e,t,n){"use strict";var a,r=n(1);window.edasprefix="acm",window.globalConfig={isParentEdas:function(){return window.parent&&-1!==window.parent.location.host.indexOf("edas")}},r.e.middleWare(function(){var e=0=e.length?{value:void 0,done:!0}:(e=a(e,t),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){var o=n(153),i=n(152);e.exports=function(r){return function(e,t){var n,e=String(i(e)),t=o(t),a=e.length;return t<0||a<=t?r?"":void 0:(n=e.charCodeAt(t))<55296||56319=e.length?(this._t=void 0,r(1)):r(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values"),o.Arguments=o.Array,a("keys"),a("values"),a("entries")},function(e,t){e.exports=function(){}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){e.exports={default:n(500),__esModule:!0}},function(e,t,n){n(501),n(506),n(507),n(508),e.exports=n(81).Symbol},function(I,A,e){"use strict";function a(e){var t=T[e]=_(M[E]);return t._k=e,t}function n(e,t){m(e);for(var n,a=B(t=g(t)),r=0,o=a.length;rr;)l(T,t=n[r++])||t==x||t==H||a.push(t);return a}function i(e){for(var t,n=e===O,a=X(n?L:g(e)),r=[],o=0;a.length>o;)!l(T,t=a[o++])||n&&!l(O,t)||r.push(T[t]);return r}var s=e(80),l=e(90),u=e(82),c=e(96),R=e(211),H=e(502).KEY,d=e(113),f=e(155),p=e(161),F=e(129),h=e(100),z=e(162),W=e(163),B=e(503),U=e(504),m=e(112),V=e(98),K=e(158),g=e(99),y=e(151),v=e(126),_=e(160),q=e(505),G=e(213),b=e(157),$=e(89),J=e(127),Q=G.f,w=$.f,X=q.f,M=s.Symbol,k=s.JSON,S=k&&k.stringify,E="prototype",x=h("_hidden"),Z=h("toPrimitive"),ee={}.propertyIsEnumerable,C=f("symbol-registry"),T=f("symbols"),L=f("op-symbols"),O=Object[E],f="function"==typeof M&&!!b.f,D=s.QObject,N=!D||!D[E]||!D[E].findChild,P=u&&d(function(){return 7!=_(w({},"a",{get:function(){return w(this,"a",{value:7}).a}})).a})?function(e,t,n){var a=Q(O,t);a&&delete O[t],w(e,t,n),a&&e!==O&&w(O,t,a)}:w,j=f&&"symbol"==typeof M.iterator?function(e){return"symbol"==typeof e}:function(e){return e instanceof M},Y=function(e,t,n){return e===O&&Y(L,t,n),m(e),t=y(t,!0),m(n),(l(T,t)?(n.enumerable?(l(e,x)&&e[x][t]&&(e[x][t]=!1),n=_(n,{enumerable:v(0,!1)})):(l(e,x)||w(e,x,v(1,{})),e[x][t]=!0),P):w)(e,t,n)};f||(R((M=function(){if(this instanceof M)throw TypeError("Symbol is not a constructor!");var t=F(0ne;)h(te[ne++]);for(var ae=J(h.store),re=0;ae.length>re;)W(ae[re++]);c(c.S+c.F*!f,"Symbol",{for:function(e){return l(C,e+="")?C[e]:C[e]=M(e)},keyFor:function(e){if(!j(e))throw TypeError(e+" is not a symbol!");for(var t in C)if(C[t]===e)return t},useSetter:function(){N=!0},useSimple:function(){N=!1}}),c(c.S+c.F*!f,"Object",{create:function(e,t){return void 0===t?_(e):n(_(e),t)},defineProperty:Y,defineProperties:n,getOwnPropertyDescriptor:r,getOwnPropertyNames:o,getOwnPropertySymbols:i});D=d(function(){b.f(1)});c(c.S+c.F*D,"Object",{getOwnPropertySymbols:function(e){return b.f(K(e))}}),k&&c(c.S+c.F*(!f||d(function(){var e=M();return"[null]"!=S([e])||"{}"!=S({a:e})||"{}"!=S(Object(e))})),"JSON",{stringify:function(e){for(var t,n,a=[e],r=1;ri;)o.call(e,a=r[i++])&&t.push(a);return t}},function(e,t,n){var a=n(209);e.exports=Array.isArray||function(e){return"Array"==a(e)}},function(e,t,n){var a=n(99),r=n(212).f,o={}.toString,i="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){if(!i||"[object Window]"!=o.call(e))return r(a(e));try{return r(e)}catch(e){return i.slice()}}},function(e,t){},function(e,t,n){n(163)("asyncIterator")},function(e,t,n){n(163)("observable")},function(e,t,n){e.exports={default:n(510),__esModule:!0}},function(e,t,n){n(511),e.exports=n(81).Object.setPrototypeOf},function(e,t,n){var a=n(96);a(a.S,"Object",{setPrototypeOf:n(512).set})},function(e,t,r){function o(e,t){if(a(e),!n(t)&&null!==t)throw TypeError(t+": can't set as prototype!")}var n=r(98),a=r(112);e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,a){try{(a=r(204)(Function.call,r(213).f(Object.prototype,"__proto__").set,2))(e,[]),n=!(e instanceof Array)}catch(e){n=!0}return function(e,t){return o(e,t),n?e.__proto__=t:a(e,t),e}}({},!1):void 0),check:o}},function(e,t,n){e.exports={default:n(514),__esModule:!0}},function(e,t,n){n(515);var a=n(81).Object;e.exports=function(e,t){return a.create(e,t)}},function(e,t,n){var a=n(96);a(a.S,"Object",{create:n(160)})},function(e,t,n){"use strict";var i=n(517);function a(){}function r(){}r.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,r,o){if(o!==i)throw(o=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types")).name="Invariant Violation",o}function t(){return e}var n={array:e.isRequired=e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:r,resetWarningCache:a};return n.PropTypes=n}},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){"use strict";function l(e,t,n,a){e.removeEventListener&&e.removeEventListener(t,n,a||!1)}function a(e,t,n,a){return e.addEventListener&&e.addEventListener(t,n,a||!1),{off:function(){return l(e,t,n,a)}}}t.__esModule=!0,t.on=a,t.once=function(r,o,i,s){return a(r,o,function e(){for(var t=arguments.length,n=Array(t),a=0;a68?1900:2e3)},r=function(t){return function(e){this[t]=+e}},o=[/[+-]\d\d:?(\d\d)?|Z/,function(e){(this.zone||(this.zone={})).offset=function(e){if(!e)return 0;if("Z"===e)return 0;var t=e.match(/([+-]|\d\d)/g),n=60*t[1]+(+t[2]||0);return 0===n?0:"+"===t[0]?-n:n}(e)}],i=function(e){var t=h[e];return t&&(t.indexOf?t:t.s.concat(t.f))},s=function(e,t){var n,a=h.meridiem;if(a){for(var r=1;r<=24;r+=1)if(e.indexOf(a(r,0,t))>-1){n=r>12;break}}else n=e===(t?"pm":"PM");return n},f={A:[n,function(e){this.afternoon=s(e,!1)}],a:[n,function(e){this.afternoon=s(e,!0)}],S:[/\d/,function(e){this.milliseconds=100*+e}],SS:[e,function(e){this.milliseconds=10*+e}],SSS:[/\d{3}/,function(e){this.milliseconds=+e}],s:[t,r("seconds")],ss:[t,r("seconds")],m:[t,r("minutes")],mm:[t,r("minutes")],H:[t,r("hours")],h:[t,r("hours")],HH:[t,r("hours")],hh:[t,r("hours")],D:[t,r("day")],DD:[e,r("day")],Do:[n,function(e){var t=h.ordinal,n=e.match(/\d+/);if(this.day=n[0],t)for(var a=1;a<=31;a+=1)t(a).replace(/\[|\]/g,"")===e&&(this.day=a)}],M:[t,r("month")],MM:[e,r("month")],MMM:[n,function(e){var t=i("months"),n=(i("monthsShort")||t.map(function(e){return e.slice(0,3)})).indexOf(e)+1;if(n<1)throw new Error;this.month=n%12||n}],MMMM:[n,function(e){var t=i("months").indexOf(e)+1;if(t<1)throw new Error;this.month=t%12||t}],Y:[/[+-]?\d+/,r("year")],YY:[e,function(e){this.year=a(e)}],YYYY:[/\d{4}/,r("year")],Z:o,ZZ:o};function b(e){var t,r;t=e,r=h&&h.formats;for(var u=(e=t.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(e,t,n){var a=n&&n.toUpperCase();return t||r[n]||l[n]||r[a].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(e,t,n){return t||n.slice(1)})})).match(d),c=u.length,n=0;n-1)return new Date(("X"===t?1e3:1)*e);var a=b(t)(e),r=a.year,o=a.month,i=a.day,s=a.hours,l=a.minutes,u=a.seconds,c=a.milliseconds,d=a.zone,f=new Date,p=i||(r||o?1:f.getDate()),h=r||f.getFullYear(),m=0;r&&!o||(m=o>0?o-1:f.getMonth());var g=s||0,y=l||0,v=u||0,_=c||0;return d?new Date(Date.UTC(h,m,p,g,y,v,_+60*d.offset*1e3)):n?new Date(Date.UTC(h,m,p,g,y,v,_)):new Date(h,m,p,g,y,v,_)}catch(e){return new Date("")}}(t,r,n),this.init(),l&&!0!==l&&(this.$L=this.locale(l).$L),s&&t!=this.format(r)&&(this.$d=new Date("")),h={}}else if(r instanceof Array)for(var u=r.length,c=1;c<=u;c+=1){a[1]=r[c-1];var d=f.apply(this,a);if(d.isValid()){this.$d=d.$d,this.$L=d.$L,this.init();break}c===u&&(this.$d=new Date(""))}else p.call(this,e)}}}()},function(e,t,n){e.exports=function(){"use strict";return function(e,t,a){a.updateLocale=function(e,t){var n=a.Ls[e];if(n)return(t?Object.keys(t):[]).forEach(function(e){n[e]=t[e]}),n}}}()},function(e,t,n){e.exports=function(e,t,n){function a(e,t,n,a,r){var o,e=e.name?e:e.$locale(),t=s(e[t]),n=s(e[n]),i=t||n.map(function(e){return e.slice(0,a)});return r?(o=e.weekStart,i.map(function(e,t){return i[(t+(o||0))%7]})):i}function r(){return n.Ls[n.locale()]}function o(e,t){return e.formats[t]||e.formats[t.toUpperCase()].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(e,t,n){return t||n.slice(1)})}var t=t.prototype,s=function(e){return e&&(e.indexOf?e:e.s)};t.localeData=function(){return function(){var t=this;return{months:function(e){return e?e.format("MMMM"):a(t,"months")},monthsShort:function(e){return e?e.format("MMM"):a(t,"monthsShort","months",3)},firstDayOfWeek:function(){return t.$locale().weekStart||0},weekdays:function(e){return e?e.format("dddd"):a(t,"weekdays")},weekdaysMin:function(e){return e?e.format("dd"):a(t,"weekdaysMin","weekdays",2)},weekdaysShort:function(e){return e?e.format("ddd"):a(t,"weekdaysShort","weekdays",3)},longDateFormat:function(e){return o(t.$locale(),e)},meridiem:this.$locale().meridiem,ordinal:this.$locale().ordinal}}.bind(this)()},n.localeData=function(){var t=r();return{firstDayOfWeek:function(){return t.weekStart||0},weekdays:function(){return n.weekdays()},weekdaysShort:function(){return n.weekdaysShort()},weekdaysMin:function(){return n.weekdaysMin()},months:function(){return n.months()},monthsShort:function(){return n.monthsShort()},longDateFormat:function(e){return o(t,e)},meridiem:t.meridiem,ordinal:t.ordinal}},n.months=function(){return a(r(),"months")},n.monthsShort=function(){return a(r(),"monthsShort","months",3)},n.weekdays=function(e){return a(r(),"weekdays",null,null,e)},n.weekdaysShort=function(e){return a(r(),"weekdaysShort","weekdays",3,e)},n.weekdaysMin=function(e){return a(r(),"weekdaysMin","weekdays",2,e)}}},function(e,t,n){e.exports=function(){"use strict";var i="month",s="quarter";return function(e,t){var n=t.prototype;n.quarter=function(e){return this.$utils().u(e)?Math.ceil((this.month()+1)/3):this.month(this.month()%3+3*(e-1))};var a=n.add;n.add=function(e,t){return e=Number(e),this.$utils().p(t)===s?this.add(3*e,i):a.bind(this)(e,t)};var o=n.startOf;n.startOf=function(e,t){var n=this.$utils(),a=!!n.u(t)||t;if(n.p(e)===s){var r=this.quarter()-1;return a?this.month(3*r).startOf(i).startOf("day"):this.month(3*r+2).endOf(i).endOf("day")}return o.bind(this)(e,t)}}}()},function(e,t,n){e.exports=function(){"use strict";return function(e,t){var n=t.prototype,o=n.format;n.format=function(e){var t=this,n=this.$locale();if(!this.isValid())return o.bind(this)(e);var a=this.$utils(),r=(e||"YYYY-MM-DDTHH:mm:ssZ").replace(/\[([^\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(e){switch(e){case"Q":return Math.ceil((t.$M+1)/3);case"Do":return n.ordinal(t.$D);case"gggg":return t.weekYear();case"GGGG":return t.isoWeekYear();case"wo":return n.ordinal(t.week(),"W");case"w":case"ww":return a.s(t.week(),"w"===e?1:2,"0");case"W":case"WW":return a.s(t.isoWeek(),"W"===e?1:2,"0");case"k":case"kk":return a.s(String(0===t.$H?24:t.$H),"k"===e?1:2,"0");case"X":return Math.floor(t.$d.getTime()/1e3);case"x":return t.$d.getTime();case"z":return"["+t.offsetName()+"]";case"zzz":return"["+t.offsetName("long")+"]";default:return e}});return o.bind(this)(r)}}}()},function(e,t,n){e.exports=function(){"use strict";var s="week",l="year";return function(e,t,i){var n=t.prototype;n.week=function(e){if(void 0===e&&(e=null),null!==e)return this.add(7*(e-this.week()),"day");var t=this.$locale().yearStart||1;if(11===this.month()&&this.date()>25){var n=i(this).startOf(l).add(1,l).date(t),a=i(this).endOf(s);if(n.isBefore(a))return 1}var r=i(this).startOf(l).date(t).startOf(s).subtract(1,"millisecond"),o=this.diff(r,s,!0);return o<0?i(this).startOf("week").week():Math.ceil(o)},n.weeks=function(e){return void 0===e&&(e=null),this.week(e)}}}()},function(e,t,n){e.exports=function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e),a={name:"zh-cn",weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),ordinal:function(e,t){return"W"===t?e+"周":e+"日"},weekStart:1,yearStart:4,formats:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah点mm分",LLLL:"YYYY年M月D日ddddAh点mm分",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},meridiem:function(e,t){var n=100*e+t;return n<600?"凌晨":n<900?"早上":n<1100?"上午":n<1300?"中午":n<1800?"下午":"晚上"}};return n.default.locale(a,null,!0),a}(n(219))},function(e,t,n){"use strict";t.__esModule=!0,t.flex=t.transition=t.animation=void 0;var r=n(215),o=n(101);function a(e){var n,a;return!!r.hasDOM&&(n=document.createElement("div"),(a=!1,o.each)(e,function(e,t){if(void 0!==n.style[t])return!(a={end:e})}),a)}var i,s;t.animation=a({WebkitAnimation:"webkitAnimationEnd",OAnimation:"oAnimationEnd",animation:"animationend"}),t.transition=a({WebkitTransition:"webkitTransitionEnd",OTransition:"oTransitionEnd",transition:"transitionend"}),t.flex=(n={display:["flex","-webkit-flex","-moz-flex","-ms-flexbox"]},!!r.hasDOM&&(i=document.createElement("div"),(s=!1,o.each)(n,function(e,t){return(0,o.each)(e,function(e){try{i.style[t]=e,s=s||i.style[t]===e}catch(e){}return!s}),!s}),s))},function(e,t,n){"use strict";t.__esModule=!0,t.getFocusNodeList=i,t.saveLastFocusNode=function(){s=document.activeElement},t.clearLastFocusNode=function(){s=null},t.backLastFocusNode=function(){if(s)try{s.focus()}catch(e){}},t.limitTabRange=function(e,t){{var n,a;t.keyCode===r.default.TAB&&(e=i(e),n=e.length-1,-1<(a=e.indexOf(document.activeElement)))&&(a=a+(t.shiftKey?-1:1),e[a=n<(a=a<0?n:a)?0:a].focus(),t.preventDefault())}};var t=n(220),r=(t=t)&&t.__esModule?t:{default:t},a=n(101);function o(e){var t=e.nodeName.toLowerCase(),n=parseInt(e.getAttribute("tabindex"),10),n=!isNaN(n)&&-1a.height)&&(r[1]=-t.top-("t"===e?t.height:0)),r},this._getParentScrollOffset=function(e){var t=0,n=0;return e&&e.offsetParent&&e.offsetParent!==document.body&&(isNaN(e.offsetParent.scrollTop)||(t+=e.offsetParent.scrollTop),isNaN(e.offsetParent.scrollLeft)||(n+=e.offsetParent.scrollLeft)),{top:t,left:n}}};var p=a;function h(e){(0,o.default)(this,h),r.call(this),this.pinElement=e.pinElement,this.baseElement=e.baseElement,this.pinFollowBaseElementWhenFixed=e.pinFollowBaseElementWhenFixed,this.container=function(e){var t=e.container,e=e.baseElement;if("undefined"==typeof document)return t;for(var n=(n=(0,i.default)(t,e))||document.body;"static"===y.dom.getStyle(n,"position");){if(!n||n===document.body)return document.body;n=n.parentNode}return n}(e),this.autoFit=e.autoFit||!1,this.align=e.align||"tl tl",this.offset=e.offset||[0,0],this.needAdjust=e.needAdjust||!1,this.isRtl=e.isRtl||!1}t.default=p,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var w=a(n(3)),M=a(n(16)),k=n(0),S=a(k),E=a(n(18)),x=a(n(196)),C=a(n(83)),T=n(11);function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(e){var t,n,a,r,o,i,s,l,u,c,d,f,p,h,m,g,y,v,_,b;return k.useState&&k.useRef&&k.useEffect?(t=void 0===(t=e.prefix)?"next-":t,r=e.animation,n=void 0===r?{in:"expandInDown",out:"expandOutUp"}:r,a=e.visible,r=e.hasMask,o=e.align,o=void 0===(s=e.points)?o?o.split(" "):void 0:s,i=e.onPosition,s=e.children,b=e.className,l=e.style,u=e.wrapperClassName,c=e.beforeOpen,d=e.onOpen,f=e.afterOpen,p=e.beforeClose,h=e.onClose,m=e.afterClose,e=(0,M.default)(e,["prefix","animation","visible","hasMask","align","points","onPosition","children","className","style","wrapperClassName","beforeOpen","onOpen","afterOpen","beforeClose","onClose","afterClose"]),g=(_=(0,k.useState)(!0))[0],y=_[1],v=(0,k.useRef)(null),_=S.default.createElement(C.default.OverlayAnimate,{visible:a,animation:n,onEnter:function(){y(!1),"function"==typeof c&&c(v.current)},onEntering:function(){"function"==typeof d&&d(v.current)},onEntered:function(){"function"==typeof f&&f(v.current)},onExit:function(){"function"==typeof p&&p(v.current)},onExiting:function(){"function"==typeof h&&h(v.current)},onExited:function(){y(!0),"function"==typeof m&&m(v.current)},timeout:300,style:l},s?(0,k.cloneElement)(s,{className:(0,E.default)([t+"overlay-inner",b,s&&s.props&&s.props.className])}):S.default.createElement("span",null)),b=(0,E.default)(((l={})[t+"overlay-wrapper v2"]=!0,l[u]=u,l.opened=a,l)),S.default.createElement(x.default,(0,w.default)({},e,{visible:a,isAnimationEnd:g,hasMask:r,wrapperClassName:b,maskClassName:t+"overlay-backdrop",maskRender:function(e){return S.default.createElement(C.default.OverlayAnimate,{visible:a,animation:!!n&&{in:"fadeIn",out:"fadeOut"},timeout:300,unmountOnExit:!0},e)},points:o,onPosition:function(e){(0,w.default)(e,{align:e.config.points}),"function"==typeof i&&i(e)},ref:v}),_)):(T.log.warning("need react version > 16.8.0"),null)},e.exports=t.default},function(n,e){function a(e,t){return n.exports=a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},n.exports.__esModule=!0,n.exports.default=n.exports,a(e,t)}n.exports=a,n.exports.__esModule=!0,n.exports.default=n.exports},function(e,t,n){"use strict";t.__esModule=!0;var a,c=g(n(16)),d=g(n(3)),r=g(n(4)),o=g(n(7)),i=g(n(8)),l=n(0),f=g(l),p=n(25),s=n(31),u=g(n(5)),h=n(11),m=g(n(362));function g(e){return e&&e.__esModule?e:{default:e}}var y,n=h.func.noop,v=h.func.makeChain,_=h.func.bindCtx,u=(y=l.Component,(0,i.default)(b,y),b.getDerivedStateFromProps=function(e,t){return"visible"in e?(0,d.default)({},t,{visible:e.visible}):null},b.prototype.componentWillUnmount=function(){var t=this;["_timer","_hideTimer","_showTimer"].forEach(function(e){t[e]&&clearTimeout(t[e])})},b.prototype.handleVisibleChange=function(e,t,n){"visible"in this.props||this.setState({visible:e}),this.props.onVisibleChange(e,t,n)},b.prototype.handleTriggerClick=function(e){this.state.visible&&!this.props.canCloseByTrigger||this.handleVisibleChange(!this.state.visible,"fromTrigger",e)},b.prototype.handleTriggerKeyDown=function(e){var t=this.props.triggerClickKeycode;(Array.isArray(t)?t:[t]).includes(e.keyCode)&&(e.preventDefault(),this.handleTriggerClick(e))},b.prototype.handleTriggerMouseEnter=function(e){var t=this;this._mouseNotFirstOnMask=!1,this._hideTimer&&(clearTimeout(this._hideTimer),this._hideTimer=null),this._showTimer&&(clearTimeout(this._showTimer),this._showTimer=null),this.state.visible||(this._showTimer=setTimeout(function(){t.handleVisibleChange(!0,"fromTrigger",e)},this.props.delay))},b.prototype.handleTriggerMouseLeave=function(e,t){var n=this;this._showTimer&&(clearTimeout(this._showTimer),this._showTimer=null),this.state.visible&&(this._hideTimer=setTimeout(function(){n.handleVisibleChange(!1,t||"fromTrigger",e)},this.props.delay))},b.prototype.handleTriggerFocus=function(e){this.handleVisibleChange(!0,"fromTrigger",e)},b.prototype.handleTriggerBlur=function(e){this._isForwardContent||this.handleVisibleChange(!1,"fromTrigger",e),this._isForwardContent=!1},b.prototype.handleContentMouseDown=function(){this._isForwardContent=!0},b.prototype.handleContentMouseEnter=function(){clearTimeout(this._hideTimer)},b.prototype.handleContentMouseLeave=function(e){this.handleTriggerMouseLeave(e,"fromContent")},b.prototype.handleMaskMouseEnter=function(){this._mouseNotFirstOnMask||(clearTimeout(this._hideTimer),this._hideTimer=null,this._mouseNotFirstOnMask=!1)},b.prototype.handleMaskMouseLeave=function(){this._mouseNotFirstOnMask=!0},b.prototype.handleRequestClose=function(e,t){this.handleVisibleChange(!1,e,t)},b.prototype.renderTrigger=function(){var e,t,n,a,r,o,i,s=this,l=this.props,u=l.trigger,l=l.disabled,c={key:"trigger","aria-haspopup":!0,"aria-expanded":this.state.visible};return this.state.visible||(c["aria-describedby"]=void 0),l||(l=this.props.triggerType,l=Array.isArray(l)?l:[l],e=u&&u.props||{},t=e.onClick,n=e.onKeyDown,a=e.onMouseEnter,r=e.onMouseLeave,o=e.onFocus,i=e.onBlur,l.forEach(function(e){switch(e){case"click":c.onClick=v(s.handleTriggerClick,t),c.onKeyDown=v(s.handleTriggerKeyDown,n);break;case"hover":c.onMouseEnter=v(s.handleTriggerMouseEnter,a),c.onMouseLeave=v(s.handleTriggerMouseLeave,r);break;case"focus":c.onFocus=v(s.handleTriggerFocus,o),c.onBlur=v(s.handleTriggerBlur,i)}})),u&&f.default.cloneElement(u,c)},b.prototype.renderContent=function(){var t=this,e=this.props,n=e.children,e=e.triggerType,e=Array.isArray(e)?e:[e],n=l.Children.only(n),a=n.props,r=a.onMouseDown,o=a.onMouseEnter,i=a.onMouseLeave,s={key:"portal"};return e.forEach(function(e){switch(e){case"focus":s.onMouseDown=v(t.handleContentMouseDown,r);break;case"hover":s.onMouseEnter=v(t.handleContentMouseEnter,o),s.onMouseLeave=v(t.handleContentMouseLeave,i)}}),f.default.cloneElement(n,s)},b.prototype.renderPortal=function(){function e(){return(0,p.findDOMNode)(t)}var t=this,n=this.props,a=n.target,r=n.safeNode,o=n.followTrigger,i=n.triggerType,s=n.hasMask,l=n.wrapperStyle,n=(0,c.default)(n,["target","safeNode","followTrigger","triggerType","hasMask","wrapperStyle"]),u=this.props.container,r=Array.isArray(r)?[].concat(r):[r],l=(r.unshift(e),l||{});return o&&(u=function(e){return e&&e.parentNode||e},l.position="relative"),"hover"===i&&s&&(n.onMaskMouseEnter=this.handleMaskMouseEnter,n.onMaskMouseLeave=this.handleMaskMouseLeave),f.default.createElement(m.default,(0,d.default)({},n,{key:"overlay",ref:function(e){return t.overlay=e},visible:this.state.visible,target:a||e,container:u,safeNode:r,wrapperStyle:l,triggerType:i,hasMask:s,onRequestClose:this.handleRequestClose}),this.props.children&&this.renderContent())},b.prototype.render=function(){return[this.renderTrigger(),this.renderPortal()]},a=i=b,i.propTypes={children:u.default.node,trigger:u.default.element,triggerType:u.default.oneOfType([u.default.string,u.default.array]),triggerClickKeycode:u.default.oneOfType([u.default.number,u.default.array]),visible:u.default.bool,defaultVisible:u.default.bool,onVisibleChange:u.default.func,disabled:u.default.bool,autoFit:u.default.bool,delay:u.default.number,canCloseByTrigger:u.default.bool,target:u.default.any,safeNode:u.default.any,followTrigger:u.default.bool,container:u.default.any,hasMask:u.default.bool,wrapperStyle:u.default.object,rtl:u.default.bool,v2:u.default.bool,placement:u.default.string,placementOffset:u.default.number,autoAdjust:u.default.bool},i.defaultProps={triggerType:"hover",triggerClickKeycode:[h.KEYCODE.SPACE,h.KEYCODE.ENTER],defaultVisible:!1,onVisibleChange:n,disabled:!1,autoFit:!1,delay:200,canCloseByTrigger:!0,followTrigger:!1,container:function(){return document.body},rtl:!1},a);function b(e){(0,r.default)(this,b);var t=(0,o.default)(this,y.call(this,e));return t.state={visible:void 0===e.visible?e.defaultVisible:e.visible},_(t,["handleTriggerClick","handleTriggerKeyDown","handleTriggerMouseEnter","handleTriggerMouseLeave","handleTriggerFocus","handleTriggerBlur","handleContentMouseEnter","handleContentMouseLeave","handleContentMouseDown","handleRequestClose","handleMaskMouseEnter","handleMaskMouseLeave"]),t}u.displayName="Popup",t.default=(0,s.polyfill)(u),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var L=a(n(3)),O=a(n(16)),D=n(0),N=a(D),P=a(n(18)),j=a(n(196)),Y=a(n(83)),I=n(11);function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(r){var e,t,o,n,a,i,s,l,u,c,d,f,p,h,m,g,y,v,_,b,w,M,k,S,E,x,C,T;return D.useState&&D.useRef&&D.useEffect?(e=void 0===(e=r.prefix)?"next-":e,E=r.animation,t=void 0===E?{in:"expandInDown",out:"expandOutUp"}:E,E=r.defaultVisible,x=r.onVisibleChange,o=void 0===x?function(){}:x,x=r.trigger,n=void 0===(n=r.triggerType)?"hover":n,C=r.overlay,a=r.onPosition,T=r.children,i=r.className,s=r.style,l=r.wrapperClassName,u=r.triggerClickKeycode,c=r.align,d=r.beforeOpen,f=r.onOpen,p=r.afterOpen,h=r.beforeClose,m=r.onClose,g=r.afterClose,y=(0,O.default)(r,["prefix","animation","defaultVisible","onVisibleChange","trigger","triggerType","overlay","onPosition","children","className","style","wrapperClassName","triggerClickKeycode","align","beforeOpen","onOpen","afterOpen","beforeClose","onClose","afterClose"]),E=(0,D.useState)(E),v=E[0],_=E[1],E=(0,D.useState)(t),b=E[0],w=E[1],M=(E=(0,D.useState)(!0))[0],k=E[1],S=(0,D.useRef)(null),(0,D.useEffect)(function(){"visible"in r&&_(r.visible)},[r.visible]),(0,D.useEffect)(function(){"animation"in r&&b!==t&&w(t)},[t]),E=C?T:x,x=N.default.createElement(Y.default.OverlayAnimate,{visible:v,animation:b,timeout:200,onEnter:function(){k(!1),"function"==typeof d&&d(S.current)},onEntering:function(){"function"==typeof f&&f(S.current)},onEntered:function(){"function"==typeof p&&p(S.current)},onExit:function(){"function"==typeof h&&h(S.current)},onExiting:function(){"function"==typeof m&&m(S.current)},onExited:function(){k(!0),"function"==typeof g&&g(S.current)},style:s},(x=C||T)?(0,D.cloneElement)(x,{className:(0,P.default)([e+"overlay-inner",i,x&&x.props&&x.props.className])}):N.default.createElement("span",null)),C=(0,P.default)(((s={})[e+"overlay-wrapper v2"]=!0,s[l]=l,s.opened=v,s)),T={},c&&(T.points=c.split(" ")),N.default.createElement(j.default.Popup,(0,L.default)({},y,T,{wrapperClassName:C,overlay:x,visible:v,isAnimationEnd:M,triggerType:n,onVisibleChange:function(e){for(var t=arguments.length,n=Array(1 16.8.0"),null)},e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var l=a(n(3)),u=a(n(16)),o=n(0),c=a(o),i=a(n(25)),s=a(n(6)),d=a(n(83)),f=a(n(165)),p=n(11);function a(e){return e&&e.__esModule?e:{default:e}}var h={top:8,maxCount:0,duration:3e3},m=s.default.config(function(e){var t=e.prefix,s=void 0===t?"next-":t,t=e.dataSource,a=void 0===t?[]:t,r=(0,o.useState)()[1];return a.forEach(function(n){n.timer||(n.timer=setTimeout(function(){var e,t=a.indexOf(n);-1a&&y.shift(),i.default.render(c.default.createElement(s.default,s.default.getContext(),c.default.createElement(m,{dataSource:y})),g),{key:n,close:function(){r.timer&&clearTimeout(r.timer);var e=y.indexOf(r);-1 16.8.0")}},e.exports=t.default},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n(565)},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var p=l(n(3)),r=l(n(4)),o=l(n(7)),a=l(n(8)),h=l(n(42)),m=l(n(0)),i=l(n(5)),g=l(n(18)),y=n(11),s=l(n(28)),v=l(n(368));function l(e){return e&&e.__esModule?e:{default:e}}function _(e,r){var o=r.size,i=r.device,s=r.labelAlign,l=r.labelTextAlign,u=r.labelCol,c=r.wrapperCol,d=r.responsive,f=r.colon;return m.default.Children.map(e,function(e){var t,n,a;return y.obj.isReactFragment(e)?_(e.props.children,r):e&&-1<["function","object"].indexOf((0,h.default)(e.type))&&"form_item"===e.type._typeMark?(t={labelCol:e.props.labelCol||u,wrapperCol:e.props.wrapperCol||c,labelAlign:e.props.labelAlign||("phone"===i?"top":s),labelTextAlign:e.props.labelTextAlign||l,colon:"colon"in e.props?e.props.colon:f,size:e.props.size||o,responsive:d},m.default.cloneElement(e,(n=t,a={},Object.keys(n).forEach(function(e){void 0!==n[e]&&(a[e]=n[e])}),a))):e})}u=m.default.Component,(0,a.default)(b,u),b.prototype.getChildContext=function(){return{_formField:this.props.field||this._formField,_formSize:this.props.size,_formDisabled:this.props.disabled,_formPreview:this.props.isPreview,_formFullWidth:this.props.fullWidth,_formLabelForErrorMessage:this.props.useLabelForErrorMessage}},b.prototype.componentDidUpdate=function(e){var t=this.props;this._formField&&("value"in t&&t.value!==e.value&&this._formField.setValues(t.value),"error"in t)&&t.error!==e.error&&this._formField.setValues(t.error)},b.prototype.render=function(){var e=this.props,t=e.className,n=e.inline,a=e.size,r=(e.device,e.labelAlign,e.labelTextAlign,e.onSubmit),o=e.children,i=(e.labelCol,e.wrapperCol,e.style),s=e.prefix,l=e.rtl,u=e.isPreview,c=e.component,d=e.responsive,f=e.gap,n=(e.colon,(0,g.default)(((e={})[s+"form"]=!0,e[s+"inline"]=n,e[""+s+a]=a,e[s+"form-responsive-grid"]=d,e[s+"form-preview"]=u,e[t]=!!t,e))),a=_(o,this.props);return m.default.createElement(c,(0,p.default)({role:"grid"},y.obj.pickOthers(b.propTypes,this.props),{className:n,style:i,dir:l?"rtl":void 0,onSubmit:r}),d?m.default.createElement(v.default,{gap:f},a):a)},a=n=b,n.propTypes={prefix:i.default.string,inline:i.default.bool,size:i.default.oneOf(["large","medium","small"]),fullWidth:i.default.bool,labelAlign:i.default.oneOf(["top","left","inset"]),labelTextAlign:i.default.oneOf(["left","right"]),field:i.default.any,saveField:i.default.func,labelCol:i.default.object,wrapperCol:i.default.object,onSubmit:i.default.func,children:i.default.any,className:i.default.string,style:i.default.object,value:i.default.object,onChange:i.default.func,component:i.default.oneOfType([i.default.string,i.default.func]),fieldOptions:i.default.object,rtl:i.default.bool,device:i.default.oneOf(["phone","tablet","desktop"]),responsive:i.default.bool,isPreview:i.default.bool,useLabelForErrorMessage:i.default.bool,colon:i.default.bool,disabled:i.default.bool,gap:i.default.oneOfType([i.default.arrayOf(i.default.number),i.default.number])},n.defaultProps={prefix:"next-",onSubmit:function(e){e.preventDefault()},size:"medium",labelAlign:"left",onChange:y.func.noop,component:"form",saveField:y.func.noop,device:"desktop",colon:!1,disabled:!1},n.childContextTypes={_formField:i.default.object,_formSize:i.default.string,_formDisabled:i.default.bool,_formPreview:i.default.bool,_formFullWidth:i.default.bool,_formLabelForErrorMessage:i.default.bool};var u,n=a;function b(e){(0,r.default)(this,b);var t,n,a=(0,o.default)(this,u.call(this,e));return a.onChange=function(e,t){a.props.onChange(a._formField.getValues(),{name:e,value:t,field:a._formField})},a._formField=null,!1!==e.field&&(t=(0,p.default)({},e.fieldOptions,{onChange:a.onChange}),e.field?(a._formField=e.field,n=a._formField.options.onChange,t.onChange=y.func.makeChain(n,a.onChange),a._formField.setOptions&&a._formField.setOptions(t)):("value"in e&&(t.values=e.value),a._formField=new s.default(a,t)),e.locale&&e.locale.Validate&&a._formField.setOptions({messages:e.locale.Validate}),e.saveField(a._formField)),a}n.displayName="Form",t.default=n,e.exports=t.default},function(e,t,n){"use strict";var a=n(91),m=(Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,a(n(169))),i=a(n(570)),r=a(n(170)),o=a(n(116)),b=a(n(171)),w=a(n(77)),s=a(n(366)),l=a(n(367)),g=a(n(577)),M=n(586),u={state:"",valueName:"value",trigger:"onChange",inputValues:[]},a=function(){function a(e){var t=this,n=1e.length)&&(t=e.length);for(var n=0,a=new Array(t);n=a.length?n:(o=a[r],n=e(t&&t[o],n,a,r+1),t?Array.isArray(t)?((a=[].concat(t))[o]=n,a):(0,l.default)({},t,(0,i.default)({},o,n)):((r=isNaN(o)?{}:[])[o]=n,r))};t=function(){};void 0!==e&&e.env,n.warning=t}.call(this,r(103))},function(e,t,n){"use strict";t.__esModule=!0,t.cloneAndAddKey=function(e){{var t;if(e&&(0,a.isValidElement)(e))return t=e.key||"error",(0,a.cloneElement)(e,{key:t})}return e},t.scrollToFirstError=function(e){var t=e.errorsGroup,n=e.options,a=e.instance;if(t&&n.scrollToFirstError){var r,o=void 0,i=void 0;for(r in t)if(t.hasOwnProperty(r)){var s=u.default.findDOMNode(a[r]);if(!s)return;var l=s.offsetTop;(void 0===i||l), use instead of.'),S.default.cloneElement(e,{className:t,size:d||C(r)})):(0,k.isValidElement)(e)?e:S.default.createElement("span",{className:a+"btn-helper"},e)}),t=c,_=(0,b.default)({},x.obj.pickOthers(Object.keys(T.propTypes),e),{type:o,disabled:p,onClick:h,className:(0,E.default)(n)});return"button"!==t&&(delete _.type,_.disabled)&&(delete _.onClick,_.href)&&delete _.href,S.default.createElement(t,(0,b.default)({},_,{dir:g?"rtl":void 0,onMouseUp:this.onMouseUp,ref:this.buttonRefHandler}),s,u)},a=n=T,n.propTypes=(0,b.default)({},s.default.propTypes,{prefix:r.default.string,rtl:r.default.bool,type:r.default.oneOf(["primary","secondary","normal"]),size:r.default.oneOf(["small","medium","large"]),icons:r.default.shape({loading:r.default.node}),iconSize:r.default.oneOfType([r.default.oneOf(["xxs","xs","small","medium","large","xl","xxl","xxxl","inherit"]),r.default.number]),htmlType:r.default.oneOf(["submit","reset","button"]),component:r.default.oneOf(["button","a","div","span"]),loading:r.default.bool,ghost:r.default.oneOf([!0,!1,"light","dark"]),text:r.default.bool,warning:r.default.bool,disabled:r.default.bool,onClick:r.default.func,className:r.default.string,onMouseUp:r.default.func,children:r.default.node}),n.defaultProps={prefix:"next-",type:"normal",size:"medium",icons:{},htmlType:"button",component:"button",loading:!1,ghost:!1,text:!1,warning:!1,disabled:!1,onClick:function(){}};var u,s=a;function T(){var e,t;(0,o.default)(this,T);for(var n=arguments.length,a=Array(n),r=0;ra[r])return!0;if(n[r] 0, or `null`');if(U(i,"numericSeparator")&&"boolean"!=typeof i.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var t=i.numericSeparator;if(void 0===n)return"undefined";if(null===n)return"null";if("boolean"==typeof n)return n?"true":"false";if("string"==typeof n)return function e(t,n){if(t.length>n.maxStringLength)return a=t.length-n.maxStringLength,a="... "+a+" more character"+(1"}if(z(n))return 0===n.length?"[]":(l=$(n,m),h&&!function(e){for(var t=0;t "+m(e,n))}),ne("Map",_.call(n),u,h)):function(e){if(w&&e&&"object"==typeof e)try{w.call(e);try{_.call(e)}catch(e){return 1}return e instanceof Set}catch(e){}return}(n)?(c=[],M&&M.call(n,function(e){c.push(m(e,n))}),ne("Set",w.call(n),c,h)):function(e){if(k&&e&&"object"==typeof e)try{k.call(e,k);try{S.call(e,S)}catch(e){return 1}return e instanceof WeakMap}catch(e){}return}(n)?q("WeakMap"):function(e){if(S&&e&&"object"==typeof e)try{S.call(e,S);try{k.call(e,k)}catch(e){return 1}return e instanceof WeakSet}catch(e){}return}(n)?q("WeakSet"):function(e){if(E&&e&&"object"==typeof e)try{return E.call(e),1}catch(e){}return}(n)?q("WeakRef"):"[object Number]"!==V(d=n)||j&&"object"==typeof d&&j in d?function(e){if(e&&"object"==typeof e&&D)try{return D.call(e),1}catch(e){}return}(n)?K(m(D.call(n))):"[object Boolean]"!==V(t=n)||j&&"object"==typeof t&&j in t?"[object String]"!==V(e=n)||j&&"object"==typeof e&&j in e?("[object Date]"!==V(t=n)||j&&"object"==typeof t&&j in t)&&!W(n)?(e=$(n,m),t=I?I(n)===Object.prototype:n instanceof Object||n.constructor===Object,f=n instanceof Object?"":"null prototype",p=!t&&j&&Object(n)===n&&j in n?x.call(V(n),8,-1):f?"Object":"",t=(!t&&"function"==typeof n.constructor&&n.constructor.name?n.constructor.name+" ":"")+(p||f?"["+O.call(L.call([],p||[],f||[]),": ")+"] ":""),0===e.length?t+"{}":h?t+"{"+G(e,h)+"}":t+"{ "+O.call(e,", ")+" }"):String(n):K(m(String(n))):K(J.call(n)):K(m(Number(n)))};var l=Object.prototype.hasOwnProperty||function(e){return e in this};function U(e,t){return l.call(e,t)}function V(e){return i.call(e)}function ee(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,a=e.length;nu&&!d&&(o=o.slice(0,u),e=C.default.createElement(m.default,{key:"_count",type:"primary",size:p,animation:!1},c(a,t))),0, as child."),a.push(t),e.props.children)&&(t.children=n(e.props.children))}),a}(e.children):t},N.prototype.fetchInfoFromBinaryChildren=function(e){function r(e,t){return t=t||0,e.forEach(function(e){e.children?t=r(e.children,t):t+=1}),t}var a=!1,o=[],i=[],e=(function t(){var e=0r.tRight&&(e=r.tRight,r.changedPageX=r.tRight-r.startLeft),e-r.cellLefto.clientHeight,o.scrollWidth,o.clientWidth,o={},e||(o[r]=0,o[a]=0),+i&&(o.marginBottom=-i,o.paddingBottom=i,e)&&(o[a]=i),h.dom.setStyle(this.headerNode,o)),n&&!this.props.lockType&&this.headerNode&&(r=this.headerNode.querySelector("."+t+"table-header-fixer"),e=h.dom.getStyle(this.headerNode,"height"),a=h.dom.getStyle(this.headerNode,"paddingBottom"),h.dom.setStyle(r,{width:i,height:e-a}))},o.prototype.render=function(){var e=this.props,t=e.components,n=e.className,a=e.prefix,r=e.fixedHeader,o=e.lockType,i=e.dataSource,e=(e.maxBodyHeight,(0,u.default)(e,["components","className","prefix","fixedHeader","lockType","dataSource","maxBodyHeight"]));return r&&((t=(0,l.default)({},t)).Header||(t.Header=m.default),t.Body||(t.Body=g.default),t.Wrapper||(t.Wrapper=y.default),n=(0,p.default)(((r={})[a+"table-fixed"]=!0,r[a+"table-wrap-empty"]=!i.length,r[n]=n,r))),d.default.createElement(s,(0,l.default)({},e,{dataSource:i,lockType:o,components:t,className:n,prefix:a}))},o}(d.default.Component),n.FixedHeader=m.default,n.FixedBody=g.default,n.FixedWrapper=y.default,n.propTypes=(0,l.default)({hasHeader:r.default.bool,fixedHeader:r.default.bool,maxBodyHeight:r.default.oneOfType([r.default.number,r.default.string])},s.propTypes),n.defaultProps=(0,l.default)({},s.defaultProps,{hasHeader:!0,fixedHeader:!1,maxBodyHeight:200,components:{},refs:{},prefix:"next-"}),n.childContextTypes={fixedHeader:r.default.bool,getNode:r.default.func,onFixedScrollSync:r.default.func,getTableInstanceForFixed:r.default.func,maxBodyHeight:r.default.oneOfType([r.default.number,r.default.string])};var t,n=t;return n.displayName="FixedTable",(0,o.statics)(n,s),n};var d=s(n(0)),r=s(n(5)),f=n(25),p=s(n(18)),h=n(11),m=s(n(136)),g=s(n(406)),y=s(n(137)),o=n(70);function s(e){return e&&e.__esModule?e:{default:e}}e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var i=o(n(16)),f=o(n(3)),r=o(n(4)),s=o(n(7)),l=o(n(8)),u=(t.default=function(o){e=t=function(n){function a(e,t){(0,r.default)(this,a);var d=(0,s.default)(this,n.call(this,e,t));return d.addSelection=function(e){var t=d.props,n=t.prefix,a=t.rowSelection,t=t.size,a=a.columnProps&&a.columnProps()||{};e.find(function(e){return"selection"===e.key})||e.unshift((0,f.default)({key:"selection",title:d.renderSelectionHeader.bind(d),cell:d.renderSelectionBody.bind(d),width:"small"===t?34:50,className:n+"table-selection "+n+"table-prerow",__normalized:!0},a))},d.renderSelectionHeader=function(){var e=d.selectAllRow,t={},n=d.props,a=n.rowSelection,r=n.primaryKey,o=n.dataSource,i=n.entireDataSource,n=n.locale,s=d.state.selectedRowKeys,l=a.mode||"multiple",u=!!s.length,c=!1,i=(d.flatDataSource(i||o).filter(function(e,t){return!a.getProps||!(a.getProps(e,t)||{}).disabled}).map(function(e){return e[r]}).forEach(function(e){-1===s.indexOf(e)?u=!1:c=!0}),t.onClick=b(function(e){e.stopPropagation()},t.onClick),a.titleProps&&a.titleProps()||{});return u&&(c=!1),["multiple"===l?p.default.createElement(h.default,(0,f.default)({key:"_total",indeterminate:c,"aria-label":n.selectAll,checked:u,onChange:e},t,i)):null,a.titleAddons&&a.titleAddons()]},d.renderSelectionBody=function(e,t,n){var a=d.props,r=a.rowSelection,a=a.primaryKey,o=d.state.selectedRowKeys,i=r.mode||"multiple",o=-1l.length&&(u=o),w(u.filter(function(e){return-1=Math.max(a-y,0)&&od.clientHeight;this.isLock()?(e=this.bodyLeftNode,t=this.bodyRightNode,n=this.getWrapperNode("right"),a=f?c:0,d=d.offsetHeight-c,f||(r[l]=0,r[u]=0),+c?(r.marginBottom=-c,r.paddingBottom=c):(r.marginBottom=-20,r.paddingBottom=20),d={"max-height":d},o||+c||(d[u]=0),+c&&(d[u]=-c),e&&g.dom.setStyle(e,d),t&&g.dom.setStyle(t,d),n&&+c&&g.dom.setStyle(n,i?"left":"right",a+"px")):(r.marginBottom=-c,r.paddingBottom=c,r[u]=0,f||(r[l]=0)),s&&g.dom.setStyle(s,r)},a.prototype.adjustHeaderSize=function(){var o=this;this.isLock()&&this.tableInc.groupChildren.forEach(function(e,t){var n=o.tableInc.groupChildren[t].length-1,n=o.getHeaderCellNode(t,n),a=o.getHeaderCellNode(t,0),r=o.getHeaderCellNode(t,0,"right"),t=o.getHeaderCellNode(t,0,"left");n&&r&&(n=n.offsetHeight,g.dom.setStyle(r,"height",n),setTimeout(function(){var e=o.tableRightInc.affixRef;return e&&e.getInstance()&&e.getInstance().updatePosition()})),a&&t&&(r=a.offsetHeight,g.dom.setStyle(t,"height",r),setTimeout(function(){var e=o.tableLeftInc.affixRef;return e&&e.getInstance()&&e.getInstance().updatePosition()}))})},a.prototype.adjustRowHeight=function(){var n=this;this.isLock()&&this.tableInc.props.dataSource.forEach(function(e,t){t=""+("object"===(void 0===e?"undefined":(0,r.default)(e))&&"__rowIndex"in e?e.__rowIndex:t)+(e.__expanded?"_expanded":"");n.setRowHeight(t,"left"),n.setRowHeight(t,"right")})},a.prototype.setRowHeight=function(e,t){var t=this.getRowNode(e,t),e=this.getRowNode(e),e=(M?e&&e.offsetHeight:e&&parseFloat(getComputedStyle(e).height))||"auto",n=(M?t&&t.offsetHeight:t&&parseFloat(getComputedStyle(t).height))||"auto";t&&e!==n&&g.dom.setStyle(t,"height",e)},a.prototype.getWrapperNode=function(e){e=e?e.charAt(0).toUpperCase()+e.substr(1):"";try{return(0,u.findDOMNode)(this["lock"+e+"El"])}catch(e){return null}},a.prototype.getRowNode=function(e,t){t=this["table"+(t=t?t.charAt(0).toUpperCase()+t.substr(1):"")+"Inc"];try{return(0,u.findDOMNode)(t.getRowRef(e))}catch(e){return null}},a.prototype.getHeaderCellNode=function(e,t,n){n=this["table"+(n=n?n.charAt(0).toUpperCase()+n.substr(1):"")+"Inc"];try{return(0,u.findDOMNode)(n.getHeaderCellRef(e,t))}catch(e){return null}},a.prototype.getCellNode=function(e,t,n){n=this["table"+(n=n?n.charAt(0).toUpperCase()+n.substr(1):"")+"Inc"];try{return(0,u.findDOMNode)(n.getCellRef(e,t))}catch(e){return null}},a.prototype.render=function(){var e,t=this.props,n=(t.children,t.columns,t.prefix),a=t.components,r=t.className,o=t.dataSource,i=t.tableWidth,t=(0,f.default)(t,["children","columns","prefix","components","className","dataSource","tableWidth"]),s=this.normalizeChildrenState(this.props),l=s.lockLeftChildren,u=s.lockRightChildren,s=s.children,c={left:this.getFlatenChildrenLength(l),right:this.getFlatenChildrenLength(u),origin:this.getFlatenChildrenLength(s)};return this._notNeedAdjustLockLeft&&(l=[]),this._notNeedAdjustLockRight&&(u=[]),this.lockLeftChildren=l,this.lockRightChildren=u,this.isOriginLock()?((a=(0,p.default)({},a)).Body=a.Body||v.default,a.Header=a.Header||_.default,a.Wrapper=a.Wrapper||b.default,a.Row=a.Row||y.default,r=(0,m.default)(((e={})[n+"table-lock"]=!0,e[n+"table-wrap-empty"]=!o.length,e[r]=r,e)),e=[h.default.createElement(d,(0,p.default)({},t,{dataSource:o,key:"lock-left",columns:l,className:n+"table-lock-left",lengths:c,prefix:n,lockType:"left",components:a,ref:this.saveLockLeftRef,loading:!1,"aria-hidden":!0})),h.default.createElement(d,(0,p.default)({},t,{dataSource:o,key:"lock-right",columns:u,className:n+"table-lock-right",lengths:c,prefix:n,lockType:"right",components:a,ref:this.saveLockRightRef,loading:!1,"aria-hidden":!0}))],h.default.createElement(d,(0,p.default)({},t,{tableWidth:i,dataSource:o,columns:s,prefix:n,lengths:c,wrapperContent:e,components:a,className:r}))):h.default.createElement(d,this.props)},a}(h.default.Component),t.LockRow=y.default,t.LockBody=v.default,t.LockHeader=_.default,t.propTypes=(0,p.default)({scrollToCol:a.default.number,scrollToRow:a.default.number},d.propTypes),t.defaultProps=(0,p.default)({},d.defaultProps),t.childContextTypes={getTableInstance:a.default.func,getLockNode:a.default.func,onLockBodyScroll:a.default.func,onRowMouseEnter:a.default.func,onRowMouseLeave:a.default.func};var e,t=e;return t.displayName="LockTable",(0,w.statics)(t,d),t},n(0)),h=d(l),u=n(25),a=d(n(5)),m=d(n(18)),c=d(n(182)),g=n(11),y=d(n(184)),v=d(n(407)),_=d(n(408)),b=d(n(137)),w=n(70);function d(e){return e&&e.__esModule?e:{default:e}}var M=g.env.ieVersion;function k(e){return function n(e){return e.map(function(e){var t=(0,p.default)({},e);return e.children&&(e.children=n(e.children)),t})}(e)}e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var l=s(n(16)),u=s(n(3)),r=s(n(4)),o=s(n(7)),i=s(n(8)),c=(t.default=function(s){e=t=function(n){function a(e,t){(0,r.default)(this,a);var c=(0,o.default)(this,n.call(this,e));return c.state={},c.updateOffsetArr=function(){var e=c.splitChildren||{},t=e.lockLeftChildren,n=e.lockRightChildren,e=e.originChildren,a=c.getFlatenChildren(t).length,r=c.getFlatenChildren(n).length,e=a+r+c.getFlatenChildren(e).length,a=0r.top-e.offset?(t?(l.position="absolute",l.top=a-(r.top-e.offset),u="relative"):(l.position="fixed",l.top=e.offset+n.top),c._setAffixStyle(l,!0),c._setContainerStyle(s)):e.bottom&&a{e=new Date(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}},function(e,t,n){"use strict";const a=n(186);class r extends Date{constructor(e){super(e+"Z"),this.isFloating=!0}toISOString(){return`${this.getUTCFullYear()}-${a(2,this.getUTCMonth()+1)}-`+a(2,this.getUTCDate())+"T"+(`${a(2,this.getUTCHours())}:${a(2,this.getUTCMinutes())}:${a(2,this.getUTCSeconds())}.`+a(3,this.getUTCMilliseconds()))}}e.exports=e=>{e=new r(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}},function(a,e,r){"use strict";!function(e){const t=r(186);class n extends e.Date{constructor(e){super(e),this.isDate=!0}toISOString(){return`${this.getUTCFullYear()}-${t(2,this.getUTCMonth()+1)}-`+t(2,this.getUTCDate())}}a.exports=e=>{e=new n(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}}.call(this,r(65))},function(e,t,n){"use strict";const a=n(186);class r extends Date{constructor(e){super(`0000-01-01T${e}Z`),this.isTime=!0}toISOString(){return`${a(2,this.getUTCHours())}:${a(2,this.getUTCMinutes())}:${a(2,this.getUTCSeconds())}.`+a(3,this.getUTCMilliseconds())}}e.exports=e=>{e=new r(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}},function(e,t,n){"use strict";!function(s){e.exports=function(r,e){e=e||{};const n=e.blocksize||40960,o=new t;return new Promise((e,t)=>{s(i,0,n,e,t)});function i(e,t,n,a){if(e>=r.length)try{return n(o.finish())}catch(e){return a(l(e,r))}try{o.parse(r.slice(e,e+t)),s(i,e+t,t,n,a)}catch(e){a(l(e,r))}}};const t=n(185),l=n(187)}.call(this,n(412).setImmediate)},function(e,t,n){!function(e,p){!function(n,o){"use strict";var a,i,s,r,l,u,t,e;function c(e){delete i[e]}function d(e){if(s)setTimeout(d,0,e);else{var t=i[e];if(t){s=!0;try{var n=t,a=n.callback,r=n.args;switch(r.length){case 0:a();break;case 1:a(r[0]);break;case 2:a(r[0],r[1]);break;case 3:a(r[0],r[1],r[2]);break;default:a.apply(o,r)}}finally{c(e),s=!1}}}}function f(){function e(e){e.source===n&&"string"==typeof e.data&&0===e.data.indexOf(t)&&d(+e.data.slice(t.length))}var t="setImmediate$"+Math.random()+"$";n.addEventListener?n.addEventListener("message",e,!1):n.attachEvent("onmessage",e),l=function(e){n.postMessage(t+e,"*")}}n.setImmediate||(a=1,s=!(i={}),r=n.document,e=(e=Object.getPrototypeOf&&Object.getPrototypeOf(n))&&e.setTimeout?e:n,"[object process]"==={}.toString.call(n.process)?l=function(e){p.nextTick(function(){d(e)})}:!function(){var e,t;if(n.postMessage&&!n.importScripts)return e=!0,t=n.onmessage,n.onmessage=function(){e=!1},n.postMessage("","*"),n.onmessage=t,e}()?l=n.MessageChannel?((t=new MessageChannel).port1.onmessage=function(e){d(e.data)},function(e){t.port2.postMessage(e)}):r&&"onreadystatechange"in r.createElement("script")?(u=r.documentElement,function(e){var t=r.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,u.removeChild(t),t=null},u.appendChild(t)}):function(e){setTimeout(d,0,e)}:f(),e.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n{let n,a=!1,r=!1;function o(){if(a=!0,!n)try{e(l.finish())}catch(e){t(e)}}function i(e){r=!0,t(e)}s.once("end",o),s.once("error",i),function e(){n=!0;let t;for(;null!==(t=s.read());)try{l.parse(t)}catch(e){return i(e)}n=!1;if(a)return o();if(r)return;s.once("readable",e)}()})}(e):function(){const a=new o;return new r.Transform({objectMode:!0,transform(e,t,n){try{a.parse(e.toString(t))}catch(e){this.emit("error",e)}n()},flush(e){try{this.push(a.finish())}catch(e){this.emit("error",e)}e()}})}()};const r=n(704),o=n(185)},function(e,t,n){e.exports=a;var c=n(188).EventEmitter;function a(){c.call(this)}n(105)(a,c),a.Readable=n(189),a.Writable=n(714),a.Duplex=n(715),a.Transform=n(716),a.PassThrough=n(717),(a.Stream=a).prototype.pipe=function(t,e){var n=this;function a(e){t.writable&&!1===t.write(e)&&n.pause&&n.pause()}function r(){n.readable&&n.resume&&n.resume()}n.on("data",a),t.on("drain",r),t._isStdio||e&&!1===e.end||(n.on("end",i),n.on("close",s));var o=!1;function i(){o||(o=!0,t.end())}function s(){o||(o=!0,"function"==typeof t.destroy&&t.destroy())}function l(e){if(u(),0===c.listenerCount(this,"error"))throw e}function u(){n.removeListener("data",a),t.removeListener("drain",r),n.removeListener("end",i),n.removeListener("close",s),n.removeListener("error",l),t.removeListener("error",l),n.removeListener("end",u),n.removeListener("close",u),t.removeListener("close",u)}return n.on("error",l),t.on("error",l),n.on("end",u),n.on("close",u),t.on("close",u),t.emit("pipe",n),t}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";t.byteLength=function(e){var e=c(e),t=e[0],e=e[1];return 3*(t+e)/4-e},t.toByteArray=function(e){var t,n,a=c(e),r=a[0],a=a[1],o=new u(function(e,t){return 3*(e+t)/4-t}(r,a)),i=0,s=0>16&255,o[i++]=t>>8&255,o[i++]=255&t;2===a&&(t=l[e.charCodeAt(n)]<<2|l[e.charCodeAt(n+1)]>>4,o[i++]=255&t);1===a&&(t=l[e.charCodeAt(n)]<<10|l[e.charCodeAt(n+1)]<<4|l[e.charCodeAt(n+2)]>>2,o[i++]=t>>8&255,o[i++]=255&t);return o},t.fromByteArray=function(e){for(var t,n=e.length,a=n%3,r=[],o=0,i=n-a;o>18&63]+s[e>>12&63]+s[e>>6&63]+s[63&e]}(a));return r.join("")}(e,o,i>2]+s[t<<4&63]+"==")):2==a&&(t=(e[n-2]<<8)+e[n-1],r.push(s[t>>10]+s[t>>4&63]+s[t<<2&63]+"="));return r.join("")};for(var s=[],l=[],u="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r=0,o=a.length;r=e.length?{value:void 0,done:!0}:(e=a(e,t),this._i+=e.length,{value:e,done:!1})})},function(e,t,n){var o=n(153),i=n(152);e.exports=function(r){return function(e,t){var n,e=String(i(e)),t=o(t),a=e.length;return t<0||a<=t?r?"":void 0:(n=e.charCodeAt(t))<55296||56319=e.length?(this._t=void 0,r(1)):r(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])},"values"),o.Arguments=o.Array,a("keys"),a("values"),a("entries")},function(e,t){e.exports=function(){}},function(e,t){e.exports=function(e,t){return{value:t,done:!!e}}},function(e,t,n){e.exports={default:n(500),__esModule:!0}},function(e,t,n){n(501),n(506),n(507),n(508),e.exports=n(81).Symbol},function(I,A,e){"use strict";function a(e){var t=T[e]=_(M[E]);return t._k=e,t}function n(e,t){m(e);for(var n,a=B(t=g(t)),r=0,o=a.length;rr;)l(T,t=n[r++])||t==x||t==H||a.push(t);return a}function i(e){for(var t,n=e===O,a=X(n?L:g(e)),r=[],o=0;a.length>o;)!l(T,t=a[o++])||n&&!l(O,t)||r.push(T[t]);return r}var s=e(80),l=e(90),u=e(82),c=e(96),R=e(211),H=e(502).KEY,d=e(113),f=e(155),p=e(161),F=e(129),h=e(100),z=e(162),W=e(163),B=e(503),U=e(504),m=e(112),V=e(98),K=e(158),g=e(99),y=e(151),v=e(126),_=e(160),q=e(505),G=e(213),b=e(157),$=e(89),J=e(127),Q=G.f,w=$.f,X=q.f,M=s.Symbol,k=s.JSON,S=k&&k.stringify,E="prototype",x=h("_hidden"),Z=h("toPrimitive"),ee={}.propertyIsEnumerable,C=f("symbol-registry"),T=f("symbols"),L=f("op-symbols"),O=Object[E],f="function"==typeof M&&!!b.f,D=s.QObject,N=!D||!D[E]||!D[E].findChild,P=u&&d(function(){return 7!=_(w({},"a",{get:function(){return w(this,"a",{value:7}).a}})).a})?function(e,t,n){var a=Q(O,t);a&&delete O[t],w(e,t,n),a&&e!==O&&w(O,t,a)}:w,j=f&&"symbol"==typeof M.iterator?function(e){return"symbol"==typeof e}:function(e){return e instanceof M},Y=function(e,t,n){return e===O&&Y(L,t,n),m(e),t=y(t,!0),m(n),(l(T,t)?(n.enumerable?(l(e,x)&&e[x][t]&&(e[x][t]=!1),n=_(n,{enumerable:v(0,!1)})):(l(e,x)||w(e,x,v(1,{})),e[x][t]=!0),P):w)(e,t,n)};f||(R((M=function(){if(this instanceof M)throw TypeError("Symbol is not a constructor!");var t=F(0ne;)h(te[ne++]);for(var ae=J(h.store),re=0;ae.length>re;)W(ae[re++]);c(c.S+c.F*!f,"Symbol",{for:function(e){return l(C,e+="")?C[e]:C[e]=M(e)},keyFor:function(e){if(!j(e))throw TypeError(e+" is not a symbol!");for(var t in C)if(C[t]===e)return t},useSetter:function(){N=!0},useSimple:function(){N=!1}}),c(c.S+c.F*!f,"Object",{create:function(e,t){return void 0===t?_(e):n(_(e),t)},defineProperty:Y,defineProperties:n,getOwnPropertyDescriptor:r,getOwnPropertyNames:o,getOwnPropertySymbols:i});D=d(function(){b.f(1)});c(c.S+c.F*D,"Object",{getOwnPropertySymbols:function(e){return b.f(K(e))}}),k&&c(c.S+c.F*(!f||d(function(){var e=M();return"[null]"!=S([e])||"{}"!=S({a:e})||"{}"!=S(Object(e))})),"JSON",{stringify:function(e){for(var t,n,a=[e],r=1;ri;)o.call(e,a=r[i++])&&t.push(a);return t}},function(e,t,n){var a=n(209);e.exports=Array.isArray||function(e){return"Array"==a(e)}},function(e,t,n){var a=n(99),r=n(212).f,o={}.toString,i="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];e.exports.f=function(e){if(!i||"[object Window]"!=o.call(e))return r(a(e));try{return r(e)}catch(e){return i.slice()}}},function(e,t){},function(e,t,n){n(163)("asyncIterator")},function(e,t,n){n(163)("observable")},function(e,t,n){e.exports={default:n(510),__esModule:!0}},function(e,t,n){n(511),e.exports=n(81).Object.setPrototypeOf},function(e,t,n){var a=n(96);a(a.S,"Object",{setPrototypeOf:n(512).set})},function(e,t,r){function o(e,t){if(a(e),!n(t)&&null!==t)throw TypeError(t+": can't set as prototype!")}var n=r(98),a=r(112);e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,a){try{(a=r(204)(Function.call,r(213).f(Object.prototype,"__proto__").set,2))(e,[]),n=!(e instanceof Array)}catch(e){n=!0}return function(e,t){return o(e,t),n?e.__proto__=t:a(e,t),e}}({},!1):void 0),check:o}},function(e,t,n){e.exports={default:n(514),__esModule:!0}},function(e,t,n){n(515);var a=n(81).Object;e.exports=function(e,t){return a.create(e,t)}},function(e,t,n){var a=n(96);a(a.S,"Object",{create:n(160)})},function(e,t,n){"use strict";var i=n(517);function a(){}function r(){}r.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,r,o){if(o!==i)throw(o=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types")).name="Invariant Violation",o}function t(){return e}var n={array:e.isRequired=e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:r,resetWarningCache:a};return n.PropTypes=n}},function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},function(e,t,n){"use strict";function l(e,t,n,a){e.removeEventListener&&e.removeEventListener(t,n,a||!1)}function a(e,t,n,a){return e.addEventListener&&e.addEventListener(t,n,a||!1),{off:function(){return l(e,t,n,a)}}}t.__esModule=!0,t.on=a,t.once=function(r,o,i,s){return a(r,o,function e(){for(var t=arguments.length,n=Array(t),a=0;a68?1900:2e3)},r=function(t){return function(e){this[t]=+e}},o=[/[+-]\d\d:?(\d\d)?|Z/,function(e){(this.zone||(this.zone={})).offset=function(e){if(!e)return 0;if("Z"===e)return 0;var t=e.match(/([+-]|\d\d)/g),n=60*t[1]+(+t[2]||0);return 0===n?0:"+"===t[0]?-n:n}(e)}],i=function(e){var t=h[e];return t&&(t.indexOf?t:t.s.concat(t.f))},s=function(e,t){var n,a=h.meridiem;if(a){for(var r=1;r<=24;r+=1)if(e.indexOf(a(r,0,t))>-1){n=r>12;break}}else n=e===(t?"pm":"PM");return n},f={A:[n,function(e){this.afternoon=s(e,!1)}],a:[n,function(e){this.afternoon=s(e,!0)}],S:[/\d/,function(e){this.milliseconds=100*+e}],SS:[e,function(e){this.milliseconds=10*+e}],SSS:[/\d{3}/,function(e){this.milliseconds=+e}],s:[t,r("seconds")],ss:[t,r("seconds")],m:[t,r("minutes")],mm:[t,r("minutes")],H:[t,r("hours")],h:[t,r("hours")],HH:[t,r("hours")],hh:[t,r("hours")],D:[t,r("day")],DD:[e,r("day")],Do:[n,function(e){var t=h.ordinal,n=e.match(/\d+/);if(this.day=n[0],t)for(var a=1;a<=31;a+=1)t(a).replace(/\[|\]/g,"")===e&&(this.day=a)}],M:[t,r("month")],MM:[e,r("month")],MMM:[n,function(e){var t=i("months"),n=(i("monthsShort")||t.map(function(e){return e.slice(0,3)})).indexOf(e)+1;if(n<1)throw new Error;this.month=n%12||n}],MMMM:[n,function(e){var t=i("months").indexOf(e)+1;if(t<1)throw new Error;this.month=t%12||t}],Y:[/[+-]?\d+/,r("year")],YY:[e,function(e){this.year=a(e)}],YYYY:[/\d{4}/,r("year")],Z:o,ZZ:o};function b(e){var t,r;t=e,r=h&&h.formats;for(var u=(e=t.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(e,t,n){var a=n&&n.toUpperCase();return t||r[n]||l[n]||r[a].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(e,t,n){return t||n.slice(1)})})).match(d),c=u.length,n=0;n-1)return new Date(("X"===t?1e3:1)*e);var a=b(t)(e),r=a.year,o=a.month,i=a.day,s=a.hours,l=a.minutes,u=a.seconds,c=a.milliseconds,d=a.zone,f=new Date,p=i||(r||o?1:f.getDate()),h=r||f.getFullYear(),m=0;r&&!o||(m=o>0?o-1:f.getMonth());var g=s||0,y=l||0,v=u||0,_=c||0;return d?new Date(Date.UTC(h,m,p,g,y,v,_+60*d.offset*1e3)):n?new Date(Date.UTC(h,m,p,g,y,v,_)):new Date(h,m,p,g,y,v,_)}catch(e){return new Date("")}}(t,r,n),this.init(),l&&!0!==l&&(this.$L=this.locale(l).$L),s&&t!=this.format(r)&&(this.$d=new Date("")),h={}}else if(r instanceof Array)for(var u=r.length,c=1;c<=u;c+=1){a[1]=r[c-1];var d=f.apply(this,a);if(d.isValid()){this.$d=d.$d,this.$L=d.$L,this.init();break}c===u&&(this.$d=new Date(""))}else p.call(this,e)}}}()},function(e,t,n){e.exports=function(){"use strict";return function(e,t,a){a.updateLocale=function(e,t){var n=a.Ls[e];if(n)return(t?Object.keys(t):[]).forEach(function(e){n[e]=t[e]}),n}}}()},function(e,t,n){e.exports=function(e,t,n){function a(e,t,n,a,r){var o,e=e.name?e:e.$locale(),t=s(e[t]),n=s(e[n]),i=t||n.map(function(e){return e.slice(0,a)});return r?(o=e.weekStart,i.map(function(e,t){return i[(t+(o||0))%7]})):i}function r(){return n.Ls[n.locale()]}function o(e,t){return e.formats[t]||e.formats[t.toUpperCase()].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(e,t,n){return t||n.slice(1)})}var t=t.prototype,s=function(e){return e&&(e.indexOf?e:e.s)};t.localeData=function(){return function(){var t=this;return{months:function(e){return e?e.format("MMMM"):a(t,"months")},monthsShort:function(e){return e?e.format("MMM"):a(t,"monthsShort","months",3)},firstDayOfWeek:function(){return t.$locale().weekStart||0},weekdays:function(e){return e?e.format("dddd"):a(t,"weekdays")},weekdaysMin:function(e){return e?e.format("dd"):a(t,"weekdaysMin","weekdays",2)},weekdaysShort:function(e){return e?e.format("ddd"):a(t,"weekdaysShort","weekdays",3)},longDateFormat:function(e){return o(t.$locale(),e)},meridiem:this.$locale().meridiem,ordinal:this.$locale().ordinal}}.bind(this)()},n.localeData=function(){var t=r();return{firstDayOfWeek:function(){return t.weekStart||0},weekdays:function(){return n.weekdays()},weekdaysShort:function(){return n.weekdaysShort()},weekdaysMin:function(){return n.weekdaysMin()},months:function(){return n.months()},monthsShort:function(){return n.monthsShort()},longDateFormat:function(e){return o(t,e)},meridiem:t.meridiem,ordinal:t.ordinal}},n.months=function(){return a(r(),"months")},n.monthsShort=function(){return a(r(),"monthsShort","months",3)},n.weekdays=function(e){return a(r(),"weekdays",null,null,e)},n.weekdaysShort=function(e){return a(r(),"weekdaysShort","weekdays",3,e)},n.weekdaysMin=function(e){return a(r(),"weekdaysMin","weekdays",2,e)}}},function(e,t,n){e.exports=function(){"use strict";var i="month",s="quarter";return function(e,t){var n=t.prototype;n.quarter=function(e){return this.$utils().u(e)?Math.ceil((this.month()+1)/3):this.month(this.month()%3+3*(e-1))};var a=n.add;n.add=function(e,t){return e=Number(e),this.$utils().p(t)===s?this.add(3*e,i):a.bind(this)(e,t)};var o=n.startOf;n.startOf=function(e,t){var n=this.$utils(),a=!!n.u(t)||t;if(n.p(e)===s){var r=this.quarter()-1;return a?this.month(3*r).startOf(i).startOf("day"):this.month(3*r+2).endOf(i).endOf("day")}return o.bind(this)(e,t)}}}()},function(e,t,n){e.exports=function(){"use strict";return function(e,t){var n=t.prototype,o=n.format;n.format=function(e){var t=this,n=this.$locale();if(!this.isValid())return o.bind(this)(e);var a=this.$utils(),r=(e||"YYYY-MM-DDTHH:mm:ssZ").replace(/\[([^\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(e){switch(e){case"Q":return Math.ceil((t.$M+1)/3);case"Do":return n.ordinal(t.$D);case"gggg":return t.weekYear();case"GGGG":return t.isoWeekYear();case"wo":return n.ordinal(t.week(),"W");case"w":case"ww":return a.s(t.week(),"w"===e?1:2,"0");case"W":case"WW":return a.s(t.isoWeek(),"W"===e?1:2,"0");case"k":case"kk":return a.s(String(0===t.$H?24:t.$H),"k"===e?1:2,"0");case"X":return Math.floor(t.$d.getTime()/1e3);case"x":return t.$d.getTime();case"z":return"["+t.offsetName()+"]";case"zzz":return"["+t.offsetName("long")+"]";default:return e}});return o.bind(this)(r)}}}()},function(e,t,n){e.exports=function(){"use strict";var s="week",l="year";return function(e,t,i){var n=t.prototype;n.week=function(e){if(void 0===e&&(e=null),null!==e)return this.add(7*(e-this.week()),"day");var t=this.$locale().yearStart||1;if(11===this.month()&&this.date()>25){var n=i(this).startOf(l).add(1,l).date(t),a=i(this).endOf(s);if(n.isBefore(a))return 1}var r=i(this).startOf(l).date(t).startOf(s).subtract(1,"millisecond"),o=this.diff(r,s,!0);return o<0?i(this).startOf("week").week():Math.ceil(o)},n.weeks=function(e){return void 0===e&&(e=null),this.week(e)}}}()},function(e,t,n){e.exports=function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e),a={name:"zh-cn",weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),ordinal:function(e,t){return"W"===t?e+"周":e+"日"},weekStart:1,yearStart:4,formats:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah点mm分",LLLL:"YYYY年M月D日ddddAh点mm分",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},meridiem:function(e,t){var n=100*e+t;return n<600?"凌晨":n<900?"早上":n<1100?"上午":n<1300?"中午":n<1800?"下午":"晚上"}};return n.default.locale(a,null,!0),a}(n(219))},function(e,t,n){"use strict";t.__esModule=!0,t.flex=t.transition=t.animation=void 0;var r=n(215),o=n(101);function a(e){var n,a;return!!r.hasDOM&&(n=document.createElement("div"),(a=!1,o.each)(e,function(e,t){if(void 0!==n.style[t])return!(a={end:e})}),a)}var i,s;t.animation=a({WebkitAnimation:"webkitAnimationEnd",OAnimation:"oAnimationEnd",animation:"animationend"}),t.transition=a({WebkitTransition:"webkitTransitionEnd",OTransition:"oTransitionEnd",transition:"transitionend"}),t.flex=(n={display:["flex","-webkit-flex","-moz-flex","-ms-flexbox"]},!!r.hasDOM&&(i=document.createElement("div"),(s=!1,o.each)(n,function(e,t){return(0,o.each)(e,function(e){try{i.style[t]=e,s=s||i.style[t]===e}catch(e){}return!s}),!s}),s))},function(e,t,n){"use strict";t.__esModule=!0,t.getFocusNodeList=i,t.saveLastFocusNode=function(){s=document.activeElement},t.clearLastFocusNode=function(){s=null},t.backLastFocusNode=function(){if(s)try{s.focus()}catch(e){}},t.limitTabRange=function(e,t){{var n,a;t.keyCode===r.default.TAB&&(e=i(e),n=e.length-1,-1<(a=e.indexOf(document.activeElement)))&&(a=a+(t.shiftKey?-1:1),e[a=n<(a=a<0?n:a)?0:a].focus(),t.preventDefault())}};var t=n(220),r=(t=t)&&t.__esModule?t:{default:t},a=n(101);function o(e){var t=e.nodeName.toLowerCase(),n=parseInt(e.getAttribute("tabindex"),10),n=!isNaN(n)&&-1a.height)&&(r[1]=-t.top-("t"===e?t.height:0)),r},this._getParentScrollOffset=function(e){var t=0,n=0;return e&&e.offsetParent&&e.offsetParent!==document.body&&(isNaN(e.offsetParent.scrollTop)||(t+=e.offsetParent.scrollTop),isNaN(e.offsetParent.scrollLeft)||(n+=e.offsetParent.scrollLeft)),{top:t,left:n}}};var p=a;function h(e){(0,o.default)(this,h),r.call(this),this.pinElement=e.pinElement,this.baseElement=e.baseElement,this.pinFollowBaseElementWhenFixed=e.pinFollowBaseElementWhenFixed,this.container=function(e){var t=e.container,e=e.baseElement;if("undefined"==typeof document)return t;for(var n=(n=(0,i.default)(t,e))||document.body;"static"===y.dom.getStyle(n,"position");){if(!n||n===document.body)return document.body;n=n.parentNode}return n}(e),this.autoFit=e.autoFit||!1,this.align=e.align||"tl tl",this.offset=e.offset||[0,0],this.needAdjust=e.needAdjust||!1,this.isRtl=e.isRtl||!1}t.default=p,e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var w=a(n(3)),M=a(n(17)),k=n(0),S=a(k),E=a(n(19)),x=a(n(196)),C=a(n(83)),T=n(11);function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(e){var t,n,a,r,o,i,s,l,u,c,d,f,p,h,m,g,y,v,_,b;return k.useState&&k.useRef&&k.useEffect?(t=void 0===(t=e.prefix)?"next-":t,r=e.animation,n=void 0===r?{in:"expandInDown",out:"expandOutUp"}:r,a=e.visible,r=e.hasMask,o=e.align,o=void 0===(s=e.points)?o?o.split(" "):void 0:s,i=e.onPosition,s=e.children,b=e.className,l=e.style,u=e.wrapperClassName,c=e.beforeOpen,d=e.onOpen,f=e.afterOpen,p=e.beforeClose,h=e.onClose,m=e.afterClose,e=(0,M.default)(e,["prefix","animation","visible","hasMask","align","points","onPosition","children","className","style","wrapperClassName","beforeOpen","onOpen","afterOpen","beforeClose","onClose","afterClose"]),g=(_=(0,k.useState)(!0))[0],y=_[1],v=(0,k.useRef)(null),_=S.default.createElement(C.default.OverlayAnimate,{visible:a,animation:n,onEnter:function(){y(!1),"function"==typeof c&&c(v.current)},onEntering:function(){"function"==typeof d&&d(v.current)},onEntered:function(){"function"==typeof f&&f(v.current)},onExit:function(){"function"==typeof p&&p(v.current)},onExiting:function(){"function"==typeof h&&h(v.current)},onExited:function(){y(!0),"function"==typeof m&&m(v.current)},timeout:300,style:l},s?(0,k.cloneElement)(s,{className:(0,E.default)([t+"overlay-inner",b,s&&s.props&&s.props.className])}):S.default.createElement("span",null)),b=(0,E.default)(((l={})[t+"overlay-wrapper v2"]=!0,l[u]=u,l.opened=a,l)),S.default.createElement(x.default,(0,w.default)({},e,{visible:a,isAnimationEnd:g,hasMask:r,wrapperClassName:b,maskClassName:t+"overlay-backdrop",maskRender:function(e){return S.default.createElement(C.default.OverlayAnimate,{visible:a,animation:!!n&&{in:"fadeIn",out:"fadeOut"},timeout:300,unmountOnExit:!0},e)},points:o,onPosition:function(e){(0,w.default)(e,{align:e.config.points}),"function"==typeof i&&i(e)},ref:v}),_)):(T.log.warning("need react version > 16.8.0"),null)},e.exports=t.default},function(n,e){function a(e,t){return n.exports=a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},n.exports.__esModule=!0,n.exports.default=n.exports,a(e,t)}n.exports=a,n.exports.__esModule=!0,n.exports.default=n.exports},function(e,t,n){"use strict";t.__esModule=!0;var a,c=g(n(17)),d=g(n(3)),r=g(n(4)),o=g(n(7)),i=g(n(8)),l=n(0),f=g(l),p=n(25),s=n(31),u=g(n(5)),h=n(11),m=g(n(362));function g(e){return e&&e.__esModule?e:{default:e}}var y,n=h.func.noop,v=h.func.makeChain,_=h.func.bindCtx,u=(y=l.Component,(0,i.default)(b,y),b.getDerivedStateFromProps=function(e,t){return"visible"in e?(0,d.default)({},t,{visible:e.visible}):null},b.prototype.componentWillUnmount=function(){var t=this;["_timer","_hideTimer","_showTimer"].forEach(function(e){t[e]&&clearTimeout(t[e])})},b.prototype.handleVisibleChange=function(e,t,n){"visible"in this.props||this.setState({visible:e}),this.props.onVisibleChange(e,t,n)},b.prototype.handleTriggerClick=function(e){this.state.visible&&!this.props.canCloseByTrigger||this.handleVisibleChange(!this.state.visible,"fromTrigger",e)},b.prototype.handleTriggerKeyDown=function(e){var t=this.props.triggerClickKeycode;(Array.isArray(t)?t:[t]).includes(e.keyCode)&&(e.preventDefault(),this.handleTriggerClick(e))},b.prototype.handleTriggerMouseEnter=function(e){var t=this;this._mouseNotFirstOnMask=!1,this._hideTimer&&(clearTimeout(this._hideTimer),this._hideTimer=null),this._showTimer&&(clearTimeout(this._showTimer),this._showTimer=null),this.state.visible||(this._showTimer=setTimeout(function(){t.handleVisibleChange(!0,"fromTrigger",e)},this.props.delay))},b.prototype.handleTriggerMouseLeave=function(e,t){var n=this;this._showTimer&&(clearTimeout(this._showTimer),this._showTimer=null),this.state.visible&&(this._hideTimer=setTimeout(function(){n.handleVisibleChange(!1,t||"fromTrigger",e)},this.props.delay))},b.prototype.handleTriggerFocus=function(e){this.handleVisibleChange(!0,"fromTrigger",e)},b.prototype.handleTriggerBlur=function(e){this._isForwardContent||this.handleVisibleChange(!1,"fromTrigger",e),this._isForwardContent=!1},b.prototype.handleContentMouseDown=function(){this._isForwardContent=!0},b.prototype.handleContentMouseEnter=function(){clearTimeout(this._hideTimer)},b.prototype.handleContentMouseLeave=function(e){this.handleTriggerMouseLeave(e,"fromContent")},b.prototype.handleMaskMouseEnter=function(){this._mouseNotFirstOnMask||(clearTimeout(this._hideTimer),this._hideTimer=null,this._mouseNotFirstOnMask=!1)},b.prototype.handleMaskMouseLeave=function(){this._mouseNotFirstOnMask=!0},b.prototype.handleRequestClose=function(e,t){this.handleVisibleChange(!1,e,t)},b.prototype.renderTrigger=function(){var e,t,n,a,r,o,i,s=this,l=this.props,u=l.trigger,l=l.disabled,c={key:"trigger","aria-haspopup":!0,"aria-expanded":this.state.visible};return this.state.visible||(c["aria-describedby"]=void 0),l||(l=this.props.triggerType,l=Array.isArray(l)?l:[l],e=u&&u.props||{},t=e.onClick,n=e.onKeyDown,a=e.onMouseEnter,r=e.onMouseLeave,o=e.onFocus,i=e.onBlur,l.forEach(function(e){switch(e){case"click":c.onClick=v(s.handleTriggerClick,t),c.onKeyDown=v(s.handleTriggerKeyDown,n);break;case"hover":c.onMouseEnter=v(s.handleTriggerMouseEnter,a),c.onMouseLeave=v(s.handleTriggerMouseLeave,r);break;case"focus":c.onFocus=v(s.handleTriggerFocus,o),c.onBlur=v(s.handleTriggerBlur,i)}})),u&&f.default.cloneElement(u,c)},b.prototype.renderContent=function(){var t=this,e=this.props,n=e.children,e=e.triggerType,e=Array.isArray(e)?e:[e],n=l.Children.only(n),a=n.props,r=a.onMouseDown,o=a.onMouseEnter,i=a.onMouseLeave,s={key:"portal"};return e.forEach(function(e){switch(e){case"focus":s.onMouseDown=v(t.handleContentMouseDown,r);break;case"hover":s.onMouseEnter=v(t.handleContentMouseEnter,o),s.onMouseLeave=v(t.handleContentMouseLeave,i)}}),f.default.cloneElement(n,s)},b.prototype.renderPortal=function(){function e(){return(0,p.findDOMNode)(t)}var t=this,n=this.props,a=n.target,r=n.safeNode,o=n.followTrigger,i=n.triggerType,s=n.hasMask,l=n.wrapperStyle,n=(0,c.default)(n,["target","safeNode","followTrigger","triggerType","hasMask","wrapperStyle"]),u=this.props.container,r=Array.isArray(r)?[].concat(r):[r],l=(r.unshift(e),l||{});return o&&(u=function(e){return e&&e.parentNode||e},l.position="relative"),"hover"===i&&s&&(n.onMaskMouseEnter=this.handleMaskMouseEnter,n.onMaskMouseLeave=this.handleMaskMouseLeave),f.default.createElement(m.default,(0,d.default)({},n,{key:"overlay",ref:function(e){return t.overlay=e},visible:this.state.visible,target:a||e,container:u,safeNode:r,wrapperStyle:l,triggerType:i,hasMask:s,onRequestClose:this.handleRequestClose}),this.props.children&&this.renderContent())},b.prototype.render=function(){return[this.renderTrigger(),this.renderPortal()]},a=i=b,i.propTypes={children:u.default.node,trigger:u.default.element,triggerType:u.default.oneOfType([u.default.string,u.default.array]),triggerClickKeycode:u.default.oneOfType([u.default.number,u.default.array]),visible:u.default.bool,defaultVisible:u.default.bool,onVisibleChange:u.default.func,disabled:u.default.bool,autoFit:u.default.bool,delay:u.default.number,canCloseByTrigger:u.default.bool,target:u.default.any,safeNode:u.default.any,followTrigger:u.default.bool,container:u.default.any,hasMask:u.default.bool,wrapperStyle:u.default.object,rtl:u.default.bool,v2:u.default.bool,placement:u.default.string,placementOffset:u.default.number,autoAdjust:u.default.bool},i.defaultProps={triggerType:"hover",triggerClickKeycode:[h.KEYCODE.SPACE,h.KEYCODE.ENTER],defaultVisible:!1,onVisibleChange:n,disabled:!1,autoFit:!1,delay:200,canCloseByTrigger:!0,followTrigger:!1,container:function(){return document.body},rtl:!1},a);function b(e){(0,r.default)(this,b);var t=(0,o.default)(this,y.call(this,e));return t.state={visible:void 0===e.visible?e.defaultVisible:e.visible},_(t,["handleTriggerClick","handleTriggerKeyDown","handleTriggerMouseEnter","handleTriggerMouseLeave","handleTriggerFocus","handleTriggerBlur","handleContentMouseEnter","handleContentMouseLeave","handleContentMouseDown","handleRequestClose","handleMaskMouseEnter","handleMaskMouseLeave"]),t}u.displayName="Popup",t.default=(0,s.polyfill)(u),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var L=a(n(3)),O=a(n(17)),D=n(0),N=a(D),P=a(n(19)),j=a(n(196)),Y=a(n(83)),I=n(11);function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(r){var e,t,o,n,a,i,s,l,u,c,d,f,p,h,m,g,y,v,_,b,w,M,k,S,E,x,C,T;return D.useState&&D.useRef&&D.useEffect?(e=void 0===(e=r.prefix)?"next-":e,E=r.animation,t=void 0===E?{in:"expandInDown",out:"expandOutUp"}:E,E=r.defaultVisible,x=r.onVisibleChange,o=void 0===x?function(){}:x,x=r.trigger,n=void 0===(n=r.triggerType)?"hover":n,C=r.overlay,a=r.onPosition,T=r.children,i=r.className,s=r.style,l=r.wrapperClassName,u=r.triggerClickKeycode,c=r.align,d=r.beforeOpen,f=r.onOpen,p=r.afterOpen,h=r.beforeClose,m=r.onClose,g=r.afterClose,y=(0,O.default)(r,["prefix","animation","defaultVisible","onVisibleChange","trigger","triggerType","overlay","onPosition","children","className","style","wrapperClassName","triggerClickKeycode","align","beforeOpen","onOpen","afterOpen","beforeClose","onClose","afterClose"]),E=(0,D.useState)(E),v=E[0],_=E[1],E=(0,D.useState)(t),b=E[0],w=E[1],M=(E=(0,D.useState)(!0))[0],k=E[1],S=(0,D.useRef)(null),(0,D.useEffect)(function(){"visible"in r&&_(r.visible)},[r.visible]),(0,D.useEffect)(function(){"animation"in r&&b!==t&&w(t)},[t]),E=C?T:x,x=N.default.createElement(Y.default.OverlayAnimate,{visible:v,animation:b,timeout:200,onEnter:function(){k(!1),"function"==typeof d&&d(S.current)},onEntering:function(){"function"==typeof f&&f(S.current)},onEntered:function(){"function"==typeof p&&p(S.current)},onExit:function(){"function"==typeof h&&h(S.current)},onExiting:function(){"function"==typeof m&&m(S.current)},onExited:function(){k(!0),"function"==typeof g&&g(S.current)},style:s},(x=C||T)?(0,D.cloneElement)(x,{className:(0,P.default)([e+"overlay-inner",i,x&&x.props&&x.props.className])}):N.default.createElement("span",null)),C=(0,P.default)(((s={})[e+"overlay-wrapper v2"]=!0,s[l]=l,s.opened=v,s)),T={},c&&(T.points=c.split(" ")),N.default.createElement(j.default.Popup,(0,L.default)({},y,T,{wrapperClassName:C,overlay:x,visible:v,isAnimationEnd:M,triggerType:n,onVisibleChange:function(e){for(var t=arguments.length,n=Array(1 16.8.0"),null)},e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var l=a(n(3)),u=a(n(17)),o=n(0),c=a(o),i=a(n(25)),s=a(n(6)),d=a(n(83)),f=a(n(165)),p=n(11);function a(e){return e&&e.__esModule?e:{default:e}}var h={top:8,maxCount:0,duration:3e3},m=s.default.config(function(e){var t=e.prefix,s=void 0===t?"next-":t,t=e.dataSource,a=void 0===t?[]:t,r=(0,o.useState)()[1];return a.forEach(function(n){n.timer||(n.timer=setTimeout(function(){var e,t=a.indexOf(n);-1a&&y.shift(),i.default.render(c.default.createElement(s.default,s.default.getContext(),c.default.createElement(m,{dataSource:y})),g),{key:n,close:function(){r.timer&&clearTimeout(r.timer);var e=y.indexOf(r);-1 16.8.0")}},e.exports=t.default},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n(565)},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";t.__esModule=!0,t.default=void 0;var p=l(n(3)),r=l(n(4)),o=l(n(7)),a=l(n(8)),h=l(n(42)),m=l(n(0)),i=l(n(5)),g=l(n(19)),y=n(11),s=l(n(28)),v=l(n(368));function l(e){return e&&e.__esModule?e:{default:e}}function _(e,r){var o=r.size,i=r.device,s=r.labelAlign,l=r.labelTextAlign,u=r.labelCol,c=r.wrapperCol,d=r.responsive,f=r.colon;return m.default.Children.map(e,function(e){var t,n,a;return y.obj.isReactFragment(e)?_(e.props.children,r):e&&-1<["function","object"].indexOf((0,h.default)(e.type))&&"form_item"===e.type._typeMark?(t={labelCol:e.props.labelCol||u,wrapperCol:e.props.wrapperCol||c,labelAlign:e.props.labelAlign||("phone"===i?"top":s),labelTextAlign:e.props.labelTextAlign||l,colon:"colon"in e.props?e.props.colon:f,size:e.props.size||o,responsive:d},m.default.cloneElement(e,(n=t,a={},Object.keys(n).forEach(function(e){void 0!==n[e]&&(a[e]=n[e])}),a))):e})}u=m.default.Component,(0,a.default)(b,u),b.prototype.getChildContext=function(){return{_formField:this.props.field||this._formField,_formSize:this.props.size,_formDisabled:this.props.disabled,_formPreview:this.props.isPreview,_formFullWidth:this.props.fullWidth,_formLabelForErrorMessage:this.props.useLabelForErrorMessage}},b.prototype.componentDidUpdate=function(e){var t=this.props;this._formField&&("value"in t&&t.value!==e.value&&this._formField.setValues(t.value),"error"in t)&&t.error!==e.error&&this._formField.setValues(t.error)},b.prototype.render=function(){var e=this.props,t=e.className,n=e.inline,a=e.size,r=(e.device,e.labelAlign,e.labelTextAlign,e.onSubmit),o=e.children,i=(e.labelCol,e.wrapperCol,e.style),s=e.prefix,l=e.rtl,u=e.isPreview,c=e.component,d=e.responsive,f=e.gap,n=(e.colon,(0,g.default)(((e={})[s+"form"]=!0,e[s+"inline"]=n,e[""+s+a]=a,e[s+"form-responsive-grid"]=d,e[s+"form-preview"]=u,e[t]=!!t,e))),a=_(o,this.props);return m.default.createElement(c,(0,p.default)({role:"grid"},y.obj.pickOthers(b.propTypes,this.props),{className:n,style:i,dir:l?"rtl":void 0,onSubmit:r}),d?m.default.createElement(v.default,{gap:f},a):a)},a=n=b,n.propTypes={prefix:i.default.string,inline:i.default.bool,size:i.default.oneOf(["large","medium","small"]),fullWidth:i.default.bool,labelAlign:i.default.oneOf(["top","left","inset"]),labelTextAlign:i.default.oneOf(["left","right"]),field:i.default.any,saveField:i.default.func,labelCol:i.default.object,wrapperCol:i.default.object,onSubmit:i.default.func,children:i.default.any,className:i.default.string,style:i.default.object,value:i.default.object,onChange:i.default.func,component:i.default.oneOfType([i.default.string,i.default.func]),fieldOptions:i.default.object,rtl:i.default.bool,device:i.default.oneOf(["phone","tablet","desktop"]),responsive:i.default.bool,isPreview:i.default.bool,useLabelForErrorMessage:i.default.bool,colon:i.default.bool,disabled:i.default.bool,gap:i.default.oneOfType([i.default.arrayOf(i.default.number),i.default.number])},n.defaultProps={prefix:"next-",onSubmit:function(e){e.preventDefault()},size:"medium",labelAlign:"left",onChange:y.func.noop,component:"form",saveField:y.func.noop,device:"desktop",colon:!1,disabled:!1},n.childContextTypes={_formField:i.default.object,_formSize:i.default.string,_formDisabled:i.default.bool,_formPreview:i.default.bool,_formFullWidth:i.default.bool,_formLabelForErrorMessage:i.default.bool};var u,n=a;function b(e){(0,r.default)(this,b);var t,n,a=(0,o.default)(this,u.call(this,e));return a.onChange=function(e,t){a.props.onChange(a._formField.getValues(),{name:e,value:t,field:a._formField})},a._formField=null,!1!==e.field&&(t=(0,p.default)({},e.fieldOptions,{onChange:a.onChange}),e.field?(a._formField=e.field,n=a._formField.options.onChange,t.onChange=y.func.makeChain(n,a.onChange),a._formField.setOptions&&a._formField.setOptions(t)):("value"in e&&(t.values=e.value),a._formField=new s.default(a,t)),e.locale&&e.locale.Validate&&a._formField.setOptions({messages:e.locale.Validate}),e.saveField(a._formField)),a}n.displayName="Form",t.default=n,e.exports=t.default},function(e,t,n){"use strict";var a=n(91),m=(Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0,a(n(169))),i=a(n(570)),r=a(n(170)),o=a(n(116)),b=a(n(171)),w=a(n(77)),s=a(n(366)),l=a(n(367)),g=a(n(577)),M=n(586),u={state:"",valueName:"value",trigger:"onChange",inputValues:[]},a=function(){function a(e){var t=this,n=1e.length)&&(t=e.length);for(var n=0,a=new Array(t);n=a.length?n:(o=a[r],n=e(t&&t[o],n,a,r+1),t?Array.isArray(t)?((a=[].concat(t))[o]=n,a):(0,l.default)({},t,(0,i.default)({},o,n)):((r=isNaN(o)?{}:[])[o]=n,r))};t=function(){};void 0!==e&&e.env,n.warning=t}.call(this,r(103))},function(e,t,n){"use strict";t.__esModule=!0,t.cloneAndAddKey=function(e){{var t;if(e&&(0,a.isValidElement)(e))return t=e.key||"error",(0,a.cloneElement)(e,{key:t})}return e},t.scrollToFirstError=function(e){var t=e.errorsGroup,n=e.options,a=e.instance;if(t&&n.scrollToFirstError){var r,o=void 0,i=void 0;for(r in t)if(t.hasOwnProperty(r)){var s=u.default.findDOMNode(a[r]);if(!s)return;var l=s.offsetTop;(void 0===i||l), use instead of.'),S.default.cloneElement(e,{className:t,size:d||C(r)})):(0,k.isValidElement)(e)?e:S.default.createElement("span",{className:a+"btn-helper"},e)}),t=c,_=(0,b.default)({},x.obj.pickOthers(Object.keys(T.propTypes),e),{type:o,disabled:p,onClick:h,className:(0,E.default)(n)});return"button"!==t&&(delete _.type,_.disabled)&&(delete _.onClick,_.href)&&delete _.href,S.default.createElement(t,(0,b.default)({},_,{dir:g?"rtl":void 0,onMouseUp:this.onMouseUp,ref:this.buttonRefHandler}),s,u)},a=n=T,n.propTypes=(0,b.default)({},s.default.propTypes,{prefix:r.default.string,rtl:r.default.bool,type:r.default.oneOf(["primary","secondary","normal"]),size:r.default.oneOf(["small","medium","large"]),icons:r.default.shape({loading:r.default.node}),iconSize:r.default.oneOfType([r.default.oneOf(["xxs","xs","small","medium","large","xl","xxl","xxxl","inherit"]),r.default.number]),htmlType:r.default.oneOf(["submit","reset","button"]),component:r.default.oneOf(["button","a","div","span"]),loading:r.default.bool,ghost:r.default.oneOf([!0,!1,"light","dark"]),text:r.default.bool,warning:r.default.bool,disabled:r.default.bool,onClick:r.default.func,className:r.default.string,onMouseUp:r.default.func,children:r.default.node}),n.defaultProps={prefix:"next-",type:"normal",size:"medium",icons:{},htmlType:"button",component:"button",loading:!1,ghost:!1,text:!1,warning:!1,disabled:!1,onClick:function(){}};var u,s=a;function T(){var e,t;(0,o.default)(this,T);for(var n=arguments.length,a=Array(n),r=0;ra[r])return!0;if(n[r] 0, or `null`');if(U(i,"numericSeparator")&&"boolean"!=typeof i.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var t=i.numericSeparator;if(void 0===n)return"undefined";if(null===n)return"null";if("boolean"==typeof n)return n?"true":"false";if("string"==typeof n)return function e(t,n){if(t.length>n.maxStringLength)return a=t.length-n.maxStringLength,a="... "+a+" more character"+(1"}if(z(n))return 0===n.length?"[]":(l=$(n,m),h&&!function(e){for(var t=0;t "+m(e,n))}),ne("Map",_.call(n),u,h)):function(e){if(w&&e&&"object"==typeof e)try{w.call(e);try{_.call(e)}catch(e){return 1}return e instanceof Set}catch(e){}return}(n)?(c=[],M&&M.call(n,function(e){c.push(m(e,n))}),ne("Set",w.call(n),c,h)):function(e){if(k&&e&&"object"==typeof e)try{k.call(e,k);try{S.call(e,S)}catch(e){return 1}return e instanceof WeakMap}catch(e){}return}(n)?q("WeakMap"):function(e){if(S&&e&&"object"==typeof e)try{S.call(e,S);try{k.call(e,k)}catch(e){return 1}return e instanceof WeakSet}catch(e){}return}(n)?q("WeakSet"):function(e){if(E&&e&&"object"==typeof e)try{return E.call(e),1}catch(e){}return}(n)?q("WeakRef"):"[object Number]"!==V(d=n)||j&&"object"==typeof d&&j in d?function(e){if(e&&"object"==typeof e&&D)try{return D.call(e),1}catch(e){}return}(n)?K(m(D.call(n))):"[object Boolean]"!==V(t=n)||j&&"object"==typeof t&&j in t?"[object String]"!==V(e=n)||j&&"object"==typeof e&&j in e?("[object Date]"!==V(t=n)||j&&"object"==typeof t&&j in t)&&!W(n)?(e=$(n,m),t=I?I(n)===Object.prototype:n instanceof Object||n.constructor===Object,f=n instanceof Object?"":"null prototype",p=!t&&j&&Object(n)===n&&j in n?x.call(V(n),8,-1):f?"Object":"",t=(!t&&"function"==typeof n.constructor&&n.constructor.name?n.constructor.name+" ":"")+(p||f?"["+O.call(L.call([],p||[],f||[]),": ")+"] ":""),0===e.length?t+"{}":h?t+"{"+G(e,h)+"}":t+"{ "+O.call(e,", ")+" }"):String(n):K(m(String(n))):K(J.call(n)):K(m(Number(n)))};var l=Object.prototype.hasOwnProperty||function(e){return e in this};function U(e,t){return l.call(e,t)}function V(e){return i.call(e)}function ee(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,a=e.length;nu&&!d&&(o=o.slice(0,u),e=C.default.createElement(m.default,{key:"_count",type:"primary",size:p,animation:!1},c(a,t))),0, as child."),a.push(t),e.props.children)&&(t.children=n(e.props.children))}),a}(e.children):t},N.prototype.fetchInfoFromBinaryChildren=function(e){function r(e,t){return t=t||0,e.forEach(function(e){e.children?t=r(e.children,t):t+=1}),t}var a=!1,o=[],i=[],e=(function t(){var e=0r.tRight&&(e=r.tRight,r.changedPageX=r.tRight-r.startLeft),e-r.cellLefto.clientHeight,o.scrollWidth,o.clientWidth,o={},e||(o[r]=0,o[a]=0),+i&&(o.marginBottom=-i,o.paddingBottom=i,e)&&(o[a]=i),h.dom.setStyle(this.headerNode,o)),n&&!this.props.lockType&&this.headerNode&&(r=this.headerNode.querySelector("."+t+"table-header-fixer"),e=h.dom.getStyle(this.headerNode,"height"),a=h.dom.getStyle(this.headerNode,"paddingBottom"),h.dom.setStyle(r,{width:i,height:e-a}))},o.prototype.render=function(){var e=this.props,t=e.components,n=e.className,a=e.prefix,r=e.fixedHeader,o=e.lockType,i=e.dataSource,e=(e.maxBodyHeight,(0,u.default)(e,["components","className","prefix","fixedHeader","lockType","dataSource","maxBodyHeight"]));return r&&((t=(0,l.default)({},t)).Header||(t.Header=m.default),t.Body||(t.Body=g.default),t.Wrapper||(t.Wrapper=y.default),n=(0,p.default)(((r={})[a+"table-fixed"]=!0,r[a+"table-wrap-empty"]=!i.length,r[n]=n,r))),d.default.createElement(s,(0,l.default)({},e,{dataSource:i,lockType:o,components:t,className:n,prefix:a}))},o}(d.default.Component),n.FixedHeader=m.default,n.FixedBody=g.default,n.FixedWrapper=y.default,n.propTypes=(0,l.default)({hasHeader:r.default.bool,fixedHeader:r.default.bool,maxBodyHeight:r.default.oneOfType([r.default.number,r.default.string])},s.propTypes),n.defaultProps=(0,l.default)({},s.defaultProps,{hasHeader:!0,fixedHeader:!1,maxBodyHeight:200,components:{},refs:{},prefix:"next-"}),n.childContextTypes={fixedHeader:r.default.bool,getNode:r.default.func,onFixedScrollSync:r.default.func,getTableInstanceForFixed:r.default.func,maxBodyHeight:r.default.oneOfType([r.default.number,r.default.string])};var t,n=t;return n.displayName="FixedTable",(0,o.statics)(n,s),n};var d=s(n(0)),r=s(n(5)),f=n(25),p=s(n(19)),h=n(11),m=s(n(136)),g=s(n(406)),y=s(n(137)),o=n(70);function s(e){return e&&e.__esModule?e:{default:e}}e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var i=o(n(17)),f=o(n(3)),r=o(n(4)),s=o(n(7)),l=o(n(8)),u=(t.default=function(o){e=t=function(n){function a(e,t){(0,r.default)(this,a);var d=(0,s.default)(this,n.call(this,e,t));return d.addSelection=function(e){var t=d.props,n=t.prefix,a=t.rowSelection,t=t.size,a=a.columnProps&&a.columnProps()||{};e.find(function(e){return"selection"===e.key})||e.unshift((0,f.default)({key:"selection",title:d.renderSelectionHeader.bind(d),cell:d.renderSelectionBody.bind(d),width:"small"===t?34:50,className:n+"table-selection "+n+"table-prerow",__normalized:!0},a))},d.renderSelectionHeader=function(){var e=d.selectAllRow,t={},n=d.props,a=n.rowSelection,r=n.primaryKey,o=n.dataSource,i=n.entireDataSource,n=n.locale,s=d.state.selectedRowKeys,l=a.mode||"multiple",u=!!s.length,c=!1,i=(d.flatDataSource(i||o).filter(function(e,t){return!a.getProps||!(a.getProps(e,t)||{}).disabled}).map(function(e){return e[r]}).forEach(function(e){-1===s.indexOf(e)?u=!1:c=!0}),t.onClick=b(function(e){e.stopPropagation()},t.onClick),a.titleProps&&a.titleProps()||{});return u&&(c=!1),["multiple"===l?p.default.createElement(h.default,(0,f.default)({key:"_total",indeterminate:c,"aria-label":n.selectAll,checked:u,onChange:e},t,i)):null,a.titleAddons&&a.titleAddons()]},d.renderSelectionBody=function(e,t,n){var a=d.props,r=a.rowSelection,a=a.primaryKey,o=d.state.selectedRowKeys,i=r.mode||"multiple",o=-1l.length&&(u=o),w(u.filter(function(e){return-1=Math.max(a-y,0)&&od.clientHeight;this.isLock()?(e=this.bodyLeftNode,t=this.bodyRightNode,n=this.getWrapperNode("right"),a=f?c:0,d=d.offsetHeight-c,f||(r[l]=0,r[u]=0),+c?(r.marginBottom=-c,r.paddingBottom=c):(r.marginBottom=-20,r.paddingBottom=20),d={"max-height":d},o||+c||(d[u]=0),+c&&(d[u]=-c),e&&g.dom.setStyle(e,d),t&&g.dom.setStyle(t,d),n&&+c&&g.dom.setStyle(n,i?"left":"right",a+"px")):(r.marginBottom=-c,r.paddingBottom=c,r[u]=0,f||(r[l]=0)),s&&g.dom.setStyle(s,r)},a.prototype.adjustHeaderSize=function(){var o=this;this.isLock()&&this.tableInc.groupChildren.forEach(function(e,t){var n=o.tableInc.groupChildren[t].length-1,n=o.getHeaderCellNode(t,n),a=o.getHeaderCellNode(t,0),r=o.getHeaderCellNode(t,0,"right"),t=o.getHeaderCellNode(t,0,"left");n&&r&&(n=n.offsetHeight,g.dom.setStyle(r,"height",n),setTimeout(function(){var e=o.tableRightInc.affixRef;return e&&e.getInstance()&&e.getInstance().updatePosition()})),a&&t&&(r=a.offsetHeight,g.dom.setStyle(t,"height",r),setTimeout(function(){var e=o.tableLeftInc.affixRef;return e&&e.getInstance()&&e.getInstance().updatePosition()}))})},a.prototype.adjustRowHeight=function(){var n=this;this.isLock()&&this.tableInc.props.dataSource.forEach(function(e,t){t=""+("object"===(void 0===e?"undefined":(0,r.default)(e))&&"__rowIndex"in e?e.__rowIndex:t)+(e.__expanded?"_expanded":"");n.setRowHeight(t,"left"),n.setRowHeight(t,"right")})},a.prototype.setRowHeight=function(e,t){var t=this.getRowNode(e,t),e=this.getRowNode(e),e=(M?e&&e.offsetHeight:e&&parseFloat(getComputedStyle(e).height))||"auto",n=(M?t&&t.offsetHeight:t&&parseFloat(getComputedStyle(t).height))||"auto";t&&e!==n&&g.dom.setStyle(t,"height",e)},a.prototype.getWrapperNode=function(e){e=e?e.charAt(0).toUpperCase()+e.substr(1):"";try{return(0,u.findDOMNode)(this["lock"+e+"El"])}catch(e){return null}},a.prototype.getRowNode=function(e,t){t=this["table"+(t=t?t.charAt(0).toUpperCase()+t.substr(1):"")+"Inc"];try{return(0,u.findDOMNode)(t.getRowRef(e))}catch(e){return null}},a.prototype.getHeaderCellNode=function(e,t,n){n=this["table"+(n=n?n.charAt(0).toUpperCase()+n.substr(1):"")+"Inc"];try{return(0,u.findDOMNode)(n.getHeaderCellRef(e,t))}catch(e){return null}},a.prototype.getCellNode=function(e,t,n){n=this["table"+(n=n?n.charAt(0).toUpperCase()+n.substr(1):"")+"Inc"];try{return(0,u.findDOMNode)(n.getCellRef(e,t))}catch(e){return null}},a.prototype.render=function(){var e,t=this.props,n=(t.children,t.columns,t.prefix),a=t.components,r=t.className,o=t.dataSource,i=t.tableWidth,t=(0,f.default)(t,["children","columns","prefix","components","className","dataSource","tableWidth"]),s=this.normalizeChildrenState(this.props),l=s.lockLeftChildren,u=s.lockRightChildren,s=s.children,c={left:this.getFlatenChildrenLength(l),right:this.getFlatenChildrenLength(u),origin:this.getFlatenChildrenLength(s)};return this._notNeedAdjustLockLeft&&(l=[]),this._notNeedAdjustLockRight&&(u=[]),this.lockLeftChildren=l,this.lockRightChildren=u,this.isOriginLock()?((a=(0,p.default)({},a)).Body=a.Body||v.default,a.Header=a.Header||_.default,a.Wrapper=a.Wrapper||b.default,a.Row=a.Row||y.default,r=(0,m.default)(((e={})[n+"table-lock"]=!0,e[n+"table-wrap-empty"]=!o.length,e[r]=r,e)),e=[h.default.createElement(d,(0,p.default)({},t,{dataSource:o,key:"lock-left",columns:l,className:n+"table-lock-left",lengths:c,prefix:n,lockType:"left",components:a,ref:this.saveLockLeftRef,loading:!1,"aria-hidden":!0})),h.default.createElement(d,(0,p.default)({},t,{dataSource:o,key:"lock-right",columns:u,className:n+"table-lock-right",lengths:c,prefix:n,lockType:"right",components:a,ref:this.saveLockRightRef,loading:!1,"aria-hidden":!0}))],h.default.createElement(d,(0,p.default)({},t,{tableWidth:i,dataSource:o,columns:s,prefix:n,lengths:c,wrapperContent:e,components:a,className:r}))):h.default.createElement(d,this.props)},a}(h.default.Component),t.LockRow=y.default,t.LockBody=v.default,t.LockHeader=_.default,t.propTypes=(0,p.default)({scrollToCol:a.default.number,scrollToRow:a.default.number},d.propTypes),t.defaultProps=(0,p.default)({},d.defaultProps),t.childContextTypes={getTableInstance:a.default.func,getLockNode:a.default.func,onLockBodyScroll:a.default.func,onRowMouseEnter:a.default.func,onRowMouseLeave:a.default.func};var e,t=e;return t.displayName="LockTable",(0,w.statics)(t,d),t},n(0)),h=d(l),u=n(25),a=d(n(5)),m=d(n(19)),c=d(n(182)),g=n(11),y=d(n(184)),v=d(n(407)),_=d(n(408)),b=d(n(137)),w=n(70);function d(e){return e&&e.__esModule?e:{default:e}}var M=g.env.ieVersion;function k(e){return function n(e){return e.map(function(e){var t=(0,p.default)({},e);return e.children&&(e.children=n(e.children)),t})}(e)}e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var l=s(n(17)),u=s(n(3)),r=s(n(4)),o=s(n(7)),i=s(n(8)),c=(t.default=function(s){e=t=function(n){function a(e,t){(0,r.default)(this,a);var c=(0,o.default)(this,n.call(this,e));return c.state={},c.updateOffsetArr=function(){var e=c.splitChildren||{},t=e.lockLeftChildren,n=e.lockRightChildren,e=e.originChildren,a=c.getFlatenChildren(t).length,r=c.getFlatenChildren(n).length,e=a+r+c.getFlatenChildren(e).length,a=0r.top-e.offset?(t?(l.position="absolute",l.top=a-(r.top-e.offset),u="relative"):(l.position="fixed",l.top=e.offset+n.top),c._setAffixStyle(l,!0),c._setContainerStyle(s)):e.bottom&&a{e=new Date(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}},function(e,t,n){"use strict";const a=n(186);class r extends Date{constructor(e){super(e+"Z"),this.isFloating=!0}toISOString(){return`${this.getUTCFullYear()}-${a(2,this.getUTCMonth()+1)}-`+a(2,this.getUTCDate())+"T"+(`${a(2,this.getUTCHours())}:${a(2,this.getUTCMinutes())}:${a(2,this.getUTCSeconds())}.`+a(3,this.getUTCMilliseconds()))}}e.exports=e=>{e=new r(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}},function(a,e,r){"use strict";!function(e){const t=r(186);class n extends e.Date{constructor(e){super(e),this.isDate=!0}toISOString(){return`${this.getUTCFullYear()}-${t(2,this.getUTCMonth()+1)}-`+t(2,this.getUTCDate())}}a.exports=e=>{e=new n(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}}.call(this,r(65))},function(e,t,n){"use strict";const a=n(186);class r extends Date{constructor(e){super(`0000-01-01T${e}Z`),this.isTime=!0}toISOString(){return`${a(2,this.getUTCHours())}:${a(2,this.getUTCMinutes())}:${a(2,this.getUTCSeconds())}.`+a(3,this.getUTCMilliseconds())}}e.exports=e=>{e=new r(e);if(isNaN(e))throw new TypeError("Invalid Datetime");return e}},function(e,t,n){"use strict";!function(s){e.exports=function(r,e){e=e||{};const n=e.blocksize||40960,o=new t;return new Promise((e,t)=>{s(i,0,n,e,t)});function i(e,t,n,a){if(e>=r.length)try{return n(o.finish())}catch(e){return a(l(e,r))}try{o.parse(r.slice(e,e+t)),s(i,e+t,t,n,a)}catch(e){a(l(e,r))}}};const t=n(185),l=n(187)}.call(this,n(412).setImmediate)},function(e,t,n){!function(e,p){!function(n,o){"use strict";var a,i,s,r,l,u,t,e;function c(e){delete i[e]}function d(e){if(s)setTimeout(d,0,e);else{var t=i[e];if(t){s=!0;try{var n=t,a=n.callback,r=n.args;switch(r.length){case 0:a();break;case 1:a(r[0]);break;case 2:a(r[0],r[1]);break;case 3:a(r[0],r[1],r[2]);break;default:a.apply(o,r)}}finally{c(e),s=!1}}}}function f(){function e(e){e.source===n&&"string"==typeof e.data&&0===e.data.indexOf(t)&&d(+e.data.slice(t.length))}var t="setImmediate$"+Math.random()+"$";n.addEventListener?n.addEventListener("message",e,!1):n.attachEvent("onmessage",e),l=function(e){n.postMessage(t+e,"*")}}n.setImmediate||(a=1,s=!(i={}),r=n.document,e=(e=Object.getPrototypeOf&&Object.getPrototypeOf(n))&&e.setTimeout?e:n,"[object process]"==={}.toString.call(n.process)?l=function(e){p.nextTick(function(){d(e)})}:!function(){var e,t;if(n.postMessage&&!n.importScripts)return e=!0,t=n.onmessage,n.onmessage=function(){e=!1},n.postMessage("","*"),n.onmessage=t,e}()?l=n.MessageChannel?((t=new MessageChannel).port1.onmessage=function(e){d(e.data)},function(e){t.port2.postMessage(e)}):r&&"onreadystatechange"in r.createElement("script")?(u=r.documentElement,function(e){var t=r.createElement("script");t.onreadystatechange=function(){d(e),t.onreadystatechange=null,u.removeChild(t),t=null},u.appendChild(t)}):function(e){setTimeout(d,0,e)}:f(),e.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n{let n,a=!1,r=!1;function o(){if(a=!0,!n)try{e(l.finish())}catch(e){t(e)}}function i(e){r=!0,t(e)}s.once("end",o),s.once("error",i),function e(){n=!0;let t;for(;null!==(t=s.read());)try{l.parse(t)}catch(e){return i(e)}n=!1;if(a)return o();if(r)return;s.once("readable",e)}()})}(e):function(){const a=new o;return new r.Transform({objectMode:!0,transform(e,t,n){try{a.parse(e.toString(t))}catch(e){this.emit("error",e)}n()},flush(e){try{this.push(a.finish())}catch(e){this.emit("error",e)}e()}})}()};const r=n(704),o=n(185)},function(e,t,n){e.exports=a;var c=n(188).EventEmitter;function a(){c.call(this)}n(105)(a,c),a.Readable=n(189),a.Writable=n(714),a.Duplex=n(715),a.Transform=n(716),a.PassThrough=n(717),(a.Stream=a).prototype.pipe=function(t,e){var n=this;function a(e){t.writable&&!1===t.write(e)&&n.pause&&n.pause()}function r(){n.readable&&n.resume&&n.resume()}n.on("data",a),t.on("drain",r),t._isStdio||e&&!1===e.end||(n.on("end",i),n.on("close",s));var o=!1;function i(){o||(o=!0,t.end())}function s(){o||(o=!0,"function"==typeof t.destroy&&t.destroy())}function l(e){if(u(),0===c.listenerCount(this,"error"))throw e}function u(){n.removeListener("data",a),t.removeListener("drain",r),n.removeListener("end",i),n.removeListener("close",s),n.removeListener("error",l),t.removeListener("error",l),n.removeListener("end",u),n.removeListener("close",u),t.removeListener("close",u)}return n.on("error",l),t.on("error",l),n.on("end",u),n.on("close",u),t.on("close",u),t.emit("pipe",n),t}},function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){"use strict";t.byteLength=function(e){var e=c(e),t=e[0],e=e[1];return 3*(t+e)/4-e},t.toByteArray=function(e){var t,n,a=c(e),r=a[0],a=a[1],o=new u(function(e,t){return 3*(e+t)/4-t}(r,a)),i=0,s=0>16&255,o[i++]=t>>8&255,o[i++]=255&t;2===a&&(t=l[e.charCodeAt(n)]<<2|l[e.charCodeAt(n+1)]>>4,o[i++]=255&t);1===a&&(t=l[e.charCodeAt(n)]<<10|l[e.charCodeAt(n+1)]<<4|l[e.charCodeAt(n+2)]>>2,o[i++]=t>>8&255,o[i++]=255&t);return o},t.fromByteArray=function(e){for(var t,n=e.length,a=n%3,r=[],o=0,i=n-a;o>18&63]+s[e>>12&63]+s[e>>6&63]+s[63&e]}(a));return r.join("")}(e,o,i>2]+s[t<<4&63]+"==")):2==a&&(t=(e[n-2]<<8)+e[n-1],r.push(s[t>>10]+s[t>>4&63]+s[t<<2&63]+"="));return r.join("")};for(var s=[],l=[],u="undefined"!=typeof Uint8Array?Uint8Array:Array,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r=0,o=a.length;r */ -t.read=function(e,t,n,a,r){var o,i,s=8*r-a-1,l=(1<>1,c=-7,d=n?r-1:0,f=n?-1:1,r=e[t+d];for(d+=f,o=r&(1<<-c)-1,r>>=-c,c+=s;0>=-c,c+=a;0>1,d=23===r?Math.pow(2,-24)-Math.pow(2,-77):0,f=a?0:o-1,p=a?1:-1,o=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,i=u):(i=Math.floor(Math.log(t)/Math.LN2),t*(a=Math.pow(2,-i))<1&&(i--,a*=2),2<=(t+=1<=i+c?d/a:d*Math.pow(2,1-c))*a&&(i++,a/=2),u<=i+c?(s=0,i=u):1<=i+c?(s=(t*a-1)*Math.pow(2,r),i+=c):(s=t*Math.pow(2,c-1)*Math.pow(2,r),i=0));8<=r;e[n+f]=255&s,f+=p,s/=256,r-=8);for(i=i<>>0),r=this.head,o=0;r;)t=r.data,n=o,t.copy(a,n),o+=r.data.length,r=r.next;return a},r),a&&a.inspect&&a.inspect.custom&&(e.exports.prototype[a.inspect.custom]=function(){var e=a.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){!function(t){function a(e){try{if(!t.localStorage)return}catch(e){return}e=t.localStorage[e];return null!=e&&"true"===String(e).toLowerCase()}e.exports=function(e,t){if(a("noDeprecation"))return e;var n=!1;return function(){if(!n){if(a("throwDeprecation"))throw new Error(t);a("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}}}.call(this,n(65))},function(e,t,n){"use strict";e.exports=r;var a=n(418),e=Object.create(n(118));function r(e){if(!(this instanceof r))return new r(e);a.call(this,e)}e.inherits=n(105),e.inherits(r,a),r.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){e.exports=n(190)},function(e,t,n){e.exports=n(92)},function(e,t,n){e.exports=n(189).Transform},function(e,t,n){e.exports=n(189).PassThrough},function(e,t,n){"use strict";function u(e){return new Error("Can only stringify objects, not "+e)}function c(t){return Object.keys(t).filter(e=>p(t[e]))}function d(e){var t,n=Array.isArray(e)?[]:Object.prototype.hasOwnProperty.call(e,"__proto__")?{["__proto__"]:void 0}:{};for(t of Object.keys(e))!e[t]||"function"!=typeof e[t].toJSON||"toISOString"in e[t]?n[t]=e[t]:n[t]=e[t].toJSON();return n}function f(t,e,n){var a,r,o=c(n=d(n));r=n,a=Object.keys(r).filter(e=>!p(r[e]));const i=[],s=e||"",l=(o.forEach(e=>{var t=h(n[e]);"undefined"!==t&&"null"!==t&&i.push(s+m(e)+" = "+g(n[e],!0))}),0{i.push(function(e,t,n,a){var r=h(a);{if("array"===r)return function(e,t,n,a){var r=h((a=d(a))[0]);if("table"!==r)throw u(r);const o=e+m(n);let i="";return a.forEach(e=>{0"\\u"+function(e,t){for(;t.lengths(e).replace(/"(?="")/g,'\\"')).join("\n");return'"'===e.slice(-1)&&(e+="\\\n"),'"""\n'+e+'"""';return}case"string":return i(t);case"string-literal":return"'"+t+"'";case"integer":return y(t);case"float":n=t;return n===1/0?"inf":n===-1/0?"-inf":Object.is(n,NaN)?"nan":Object.is(n,-0)?"-0.0":([n,a]=String(n).split("."),y(n)+"."+a);case"boolean":return String(t);case"datetime":return t.toISOString();case"array":{var a=t.filter(e=>"null"!==h(e)&&"undefined"!==h(e)&&"nan"!==h(e));a=d(a);let e="[";a=a.map(e=>l(e));60{o.push(m(e)+" = "+g(r[e],!1))}),"{ "+o.join(", ")+(0=P.KEYCODE.LEFT&&t<=P.KEYCODE.DOWN&&e.preventDefault(),e=void 0,t===P.KEYCODE.RIGHT||t===P.KEYCODE.DOWN?(e=o.getNextActiveKey(!0),o.handleTriggerEvent(o.props.triggerType,e)):t!==P.KEYCODE.LEFT&&t!==P.KEYCODE.UP||(e=o.getNextActiveKey(!1),o.handleTriggerEvent(o.props.triggerType,e)))},o.state={activeKey:o.getDefaultActiveKey(e)},o}s.displayName="Tab",t.default=(0,l.polyfill)(s),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var _=d(n(3)),a=d(n(4)),r=d(n(7)),o=d(n(8)),b=d(n(0)),i=n(25),s=d(n(5)),w=d(n(18)),M=d(n(26)),l=d(n(64)),u=d(n(50)),k=(d(n(20)),d(n(83))),h=n(11),c=n(420);function d(e){return e&&e.__esModule?e:{default:e}}var f,S={float:"right",zIndex:1},E={float:"left",zIndex:1},p={dropdown:"arrow-down",prev:"arrow-left",next:"arrow-right"},m=l.default.Popup,l=(f=b.default.Component,(0,o.default)(g,f),g.prototype.componentDidMount=function(){this.props.animation||this.initialSettings(),h.events.on(window,"resize",this.onWindowResized)},g.prototype.componentDidUpdate=function(e){var t=this;clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(function(){t.scrollToActiveTab()},410),clearTimeout(this.slideTimer),this.slideTimer=setTimeout(function(){t.setSlideBtn()},410),"dropdown"!==this.props.excessMode||(0,c.tabsArrayShallowEqual)(this.props.tabs,e.tabs)||this.getDropdownItems(this.props)},g.prototype.componentWillUnmount=function(){h.events.off(window,"resize",this.onWindowResized)},g.prototype.initialSettings=function(){this.setSlideBtn(),this.getDropdownItems(this.props)},g.prototype.setOffset=function(e){var t=!(1n&&(t.current=n),this.setState(t),this.props.onPageSizeChange(e)},I.prototype.renderPageTotal=function(){var e=this.props,t=e.prefix,n=e.total,e=e.totalRender,a=this.state,r=a.currentPageSize,a=a.current;return N.default.createElement("div",{className:t+"pagination-total"},e(n,[(a-1)*r+1,a*r]))},I.prototype.renderPageItem=function(e){var t=this.props,n=t.prefix,a=t.size,r=t.link,o=t.pageNumberRender,i=t.total,s=t.pageSize,t=t.locale,l=this.state.current,i=Y(i,s),s=parseInt(e,10)===l,a={size:a,className:(0,P.default)(((l={})[n+"pagination-item"]=!0,l[n+"current"]=s,l)),onClick:s?m:this.onPageItemClick.bind(this,e)};return r&&(a.component="a",a.href=r.replace("{page}",e)),N.default.createElement(d.default,(0,D.default)({"aria-label":j.str.template(t.total,{current:e,total:i})},a,{key:e}),o(e))},I.prototype.renderPageFirst=function(e){var t=this.props,n=t.prefix,a=t.size,r=t.shape,t=t.locale,a={disabled:e<=1,size:a,className:(0,P.default)(((a={})[n+"pagination-item"]=!0,a[n+"prev"]=!0,a)),onClick:this.onPageItemClick.bind(this,e-1)},n=N.default.createElement(c.default,{type:"arrow-left",className:n+"pagination-icon-prev"});return N.default.createElement(d.default,(0,D.default)({},a,{"aria-label":j.str.template(t.labelPrev,{current:e})}),n,"arrow-only"===r||"arrow-prev-only"===r||"no-border"===r?"":t.prev)},I.prototype.renderPageLast=function(e,t){var n=this.props,a=n.prefix,r=n.size,o=n.shape,n=n.locale,r={disabled:t<=e,size:r,className:(0,P.default)(((t={})[a+"pagination-item"]=!0,t[a+"next"]=!0,t)),onClick:this.onPageItemClick.bind(this,e+1)},t=N.default.createElement(c.default,{type:"arrow-right",className:a+"pagination-icon-next"});return N.default.createElement(d.default,(0,D.default)({},r,{"aria-label":j.str.template(n.labelNext,{current:e})}),"arrow-only"===o||"no-border"===o?"":n.next,t)},I.prototype.renderPageEllipsis=function(e){var t=this.props.prefix;return N.default.createElement(c.default,{className:t+"pagination-ellipsis "+t+"pagination-icon-ellipsis",type:"ellipsis",key:"ellipsis-"+e})},I.prototype.renderPageJump=function(){var t=this,e=this.props,n=e.prefix,a=e.size,e=e.locale,r=this.state.inputValue;return[N.default.createElement("span",{className:n+"pagination-jump-text"},e.goTo),N.default.createElement(f.default,{className:n+"pagination-jump-input",type:"text","aria-label":e.inputAriaLabel,size:a,value:r,onChange:this.onInputChange.bind(this),onKeyDown:function(e){e.keyCode===j.KEYCODE.ENTER&&t.handleJump(e)}}),N.default.createElement("span",{className:n+"pagination-jump-text"},e.page),N.default.createElement(d.default,{className:n+"pagination-jump-go",size:a,onClick:this.handleJump},e.go)]},I.prototype.renderPageDisplay=function(e,t){var n=this.props,a=n.prefix,n=n.pageNumberRender;return N.default.createElement("span",{className:a+"pagination-display"},N.default.createElement("em",null,n(e)),"/",n(t))},I.prototype.renderPageList=function(e,t){var n=this.props,a=n.prefix,n=n.pageShowCount,r=[];if(t<=n)for(var o=1;o<=t;o++)r.push(this.renderPageItem(o));else{var n=n-3,i=parseInt(n/2,10),s=void 0,l=void 0;r.push(this.renderPageItem(1)),l=e+i,(s=e-i)<=1&&(l=(s=2)+n),2=e.length&&-1=this.props.children.length?(this.update(this.props),this.changeSlide({message:"index",index:this.props.children.length-this.props.slidesToShow,currentSlide:this.state.currentSlide})):(n=[],Object.keys(t).forEach(function(e){e in a.props&&t[e]!==a.props[e]&&n.push(e)}),1===n.length&&"children"===n[0]||l.obj.shallowEqual(t,this.props)||this.update(this.props)),this.adaptHeight()},p.prototype.componentWillUnmount=function(){this.animationEndCallback&&clearTimeout(this.animationEndCallback),l.events.off(window,"resize",this.onWindowResized),this.state.autoPlayTimer&&clearInterval(this.state.autoPlayTimer)},p.prototype.onWindowResized=function(){this.update(this.props),this.setState({animating:!1}),clearTimeout(this.animationEndCallback),delete this.animationEndCallback},p.prototype.slickGoTo=function(e){"number"==typeof e&&this.changeSlide({message:"index",index:e,currentSlide:this.state.currentSlide})},p.prototype.onEnterArrow=function(e){this.arrowHoverHandler(e)},p.prototype.onLeaveArrow=function(){this.arrowHoverHandler()},p.prototype._instanceRefHandler=function(e,t){this[e]=t},p.prototype.render=function(){var e=this.props,t=e.prefix,n=e.animation,a=e.arrows,r=e.arrowSize,o=e.arrowPosition,i=e.arrowDirection,s=e.dots,l=e.dotsClass,u=e.cssEase,c=e.speed,d=e.infinite,f=e.centerMode,p=e.centerPadding,h=e.lazyLoad,m=e.dotsDirection,g=e.rtl,y=e.slidesToShow,v=e.slidesToScroll,_=e.variableWidth,b=e.vertical,w=e.verticalSwiping,M=e.focusOnSelect,k=e.children,S=e.dotsRender,e=e.triggerType,E=this.state,x=E.currentSlide,C=E.lazyLoadedList,T=E.slideCount,L=E.slideWidth,O=E.slideHeight,D=E.trackStyle,N=E.listHeight,E=E.dragging,u={prefix:t,animation:n,cssEase:u,speed:c,infinite:d,centerMode:f,focusOnSelect:M?this.selectHandler:null,currentSlide:x,lazyLoad:h,lazyLoadedList:C,rtl:g,slideWidth:L,slideHeight:O,slidesToShow:y,slidesToScroll:v,slideCount:T,trackStyle:D,variableWidth:_,vertical:b,verticalSwiping:w,triggerType:e},c=void 0,h=(!0===s&&yt.startX?1:-1),!0===this.props.verticalSwiping&&(t.swipeLength=Math.round(Math.sqrt(Math.pow(t.curY-t.startY,2))),a=t.curY>t.startY?1:-1),r=this.state.currentSlide,s=Math.ceil(this.state.slideCount/this.props.slidesToScroll),o=this.swipeDirection(this.state.touchObject),i=t.swipeLength,!1===this.props.infinite&&(0===r&&"right"===o||s<=r+1&&"left"===o)&&(i=t.swipeLength*this.props.edgeFriction,!1===this.state.edgeDragged)&&this.props.edgeEvent&&(this.props.edgeEvent(o),this.setState({edgeDragged:!0})),!1===this.state.swiped&&this.props.swipeEvent&&(this.props.swipeEvent(o),this.setState({swiped:!0})),this.setState({touchObject:t,swipeLeft:s=n+i*a,trackStyle:(0,u.getTrackCSS)((0,l.default)({left:s},this.props,this.state))}),Math.abs(t.curX-t.startX)<.8*Math.abs(t.curY-t.startY))||4t[t.length-1])e=t[t.length-1];else for(var a in t){if(e-1*n.state.swipeLeft)return t=e,!1}else if(e.offsetLeft-a+(n.getWidth(e)||0)/2>-1*n.state.swipeLeft)return t=e,!1;return!0}),Math.abs(t.dataset.index-this.state.currentSlide)||1):this.props.slidesToScroll},swipeEnd:function(e){if(this.state.dragging){var t=this.state.touchObject,n=this.state.listWidth/this.props.touchThreshold,a=this.swipeDirection(t);if(this.props.verticalSwiping&&(n=this.state.listHeight/this.props.touchThreshold),this.setState({dragging:!1,edgeDragged:!1,swiped:!1,swipeLeft:null,touchObject:{}}),t.swipeLength)if(t.swipeLength>n){e.preventDefault();var r=void 0,o=void 0;switch(a){case"left":case"down":o=this.state.currentSlide+this.getSlideCount(),r=this.props.swipeToSlide?this.checkNavigable(o):o,this.setState({currentDirection:0});break;case"right":case"up":o=this.state.currentSlide-this.getSlideCount(),r=this.props.swipeToSlide?this.checkNavigable(o):o,this.setState({currentDirection:1});break;default:r=this.state.currentSlide}this.slideHandler(r)}else{t=(0,u.getTrackLeft)((0,l.default)({slideIndex:this.state.currentSlide,trackRef:this.track},this.props,this.state));this.setState({trackStyle:(0,u.getTrackAnimateCSS)((0,l.default)({left:t},this.props,this.state))})}}else this.props.swipe&&e.preventDefault()},onInnerSliderEnter:function(){this.props.autoplay&&this.props.pauseOnHover&&this.pause()},onInnerSliderLeave:function(){this.props.autoplay&&this.props.pauseOnHover&&this.autoPlay()}},e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var g=a(n(3)),c=a(n(0)),d=a(n(25)),y=n(423);function a(e){return e&&e.__esModule?e:{default:e}}t.default={initialize:function(t){var n=this,e=d.default.findDOMNode(this.list),a=c.default.Children.count(t.children),r=this.getWidth(e)||0,o=this.getWidth(d.default.findDOMNode(this.track))||0,i=void 0,e=(i=t.vertical?r:(r-(t.centerMode&&2*parseInt(t.centerPadding)))/t.slidesToShow,this.getHeight(e.querySelector('[data-index="0"]'))||0),s=e*t.slidesToShow,l=t.slidesToShow||1,u="activeIndex"in t?t.activeIndex:t.defaultActiveIndex,l=t.rtl?a-1-(l-1)-u:u;this.setState({slideCount:a,slideWidth:i,listWidth:r,trackWidth:o,currentSlide:l,slideHeight:e,listHeight:s},function(){var e=(0,y.getTrackLeft)((0,g.default)({slideIndex:n.state.currentSlide,trackRef:n.track},t,n.state)),e=(0,y.getTrackCSS)((0,g.default)({left:e},t,n.state));n.setState({trackStyle:e}),n.autoPlay()})},update:function(e){this.initialize(e)},getWidth:function(e){return"clientWidth"in e?e.clientWidth:e&&e.getBoundingClientRect().width},getHeight:function(e){return"clientHeight"in e?e.clientHeight:e&&e.getBoundingClientRect().height},adaptHeight:function(){var e,t;this.props.adaptiveHeight&&(t='[data-index="'+this.state.currentSlide+'"]',this.list)&&(t=(e=d.default.findDOMNode(this.list)).querySelector(t).offsetHeight,e.style.height=t+"px")},canGoNext:function(e){var t=!0;return e.infinite||(e.centerMode?e.currentSlide>=e.slideCount-1&&(t=!1):(e.slideCount<=e.slidesToShow||e.currentSlide>=e.slideCount-e.slidesToShow)&&(t=!1)),t},slideHandler:function(e){var t=this,n=this.props.rtl,a=void 0,r=void 0,o=void 0;if(!this.props.waitForAnimate||!this.state.animating){if("fade"===this.props.animation)return r=this.state.currentSlide,!1===this.props.infinite&&(e<0||e>=this.state.slideCount)?void 0:(a=e<0?e+this.state.slideCount:e>=this.state.slideCount?e-this.state.slideCount:e,this.props.lazyLoad&&this.state.lazyLoadedList.indexOf(a)<0&&this.setState({lazyLoadedList:this.state.lazyLoadedList.concat(a)}),o=function(){t.setState({animating:!1}),t.props.onChange(a),delete t.animationEndCallback},this.props.onBeforeChange(this.state.currentSlide,a),this.setState({animating:!0,currentSlide:a},function(){this.animationEndCallback=setTimeout(o,this.props.speed+20)}),void this.autoPlay());a=e,n?a<0?!1===this.props.infinite?r=0:this.state.slideCount%this.props.slidesToScroll!=0?a+this.props.slidesToScroll<=0?(r=this.state.slideCount+a,a=this.state.slideCount-this.props.slidesToScroll):r=a=0:r=this.state.slideCount+a:r=a>=this.state.slideCount?!1===this.props.infinite?this.state.slideCount-this.props.slidesToShow:this.state.slideCount%this.props.slidesToScroll!=0?0:a-this.state.slideCount:a:r=a<0?!1===this.props.infinite?0:this.state.slideCount%this.props.slidesToScroll!=0?this.state.slideCount-this.state.slideCount%this.props.slidesToScroll:this.state.slideCount+a:a>=this.state.slideCount?!1===this.props.infinite?this.state.slideCount-this.props.slidesToShow:this.state.slideCount%this.props.slidesToScroll!=0?0:a-this.state.slideCount:a;var i,e=(0,y.getTrackLeft)((0,g.default)({slideIndex:a,trackRef:this.track},this.props,this.state)),s=(0,y.getTrackLeft)((0,g.default)({slideIndex:r,trackRef:this.track},this.props,this.state));if(!1===this.props.infinite&&(e=s),this.props.lazyLoad){for(var l=!0,u=[],c=this.state.slideCount,d=a<0?c+a:r,f=d;f=l.activeIndex?"visible":"hidden",c.transition="opacity "+l.speed+"ms "+l.cssEase,c.WebkitTransition="opacity "+l.speed+"ms "+l.cssEase,l.vertical?c.top=-l.activeIndex*l.slideHeight:c.left=-l.activeIndex*l.slideWidth),l.vertical&&(c.width="100%"),c),u=(c=(0,v.default)({activeIndex:e},d),a=c.prefix,u=r=i=void 0,o=(u=c.rtl?c.slideCount-1-c.activeIndex:c.activeIndex)<0||u>=c.slideCount,c.centerMode?(n=Math.floor(c.slidesToShow/2),r=(u-c.currentSlide)%c.slideCount==0,u>c.currentSlide-n-1&&u<=c.currentSlide+n&&(i=!0)):i=c.currentSlide<=u&&u=u,u=(0,k.default)(((v={})[o+"upload-list-item"]=!0,v[o+"hidden"]=u,v)),v=this.props.children||i.card.addPhoto,d=r?S.func.prevent:d,_=S.obj.pickOthers(C.propTypes,this.props),b=S.obj.pickOthers(E.default.propTypes,_);if(h&&"function"==typeof m)return e=(0,k.default)(((e={})[o+"form-preview"]=!0,e[s]=!!s,e)),M.default.createElement("div",{style:l,className:e},m(this.state.value,this.props));return M.default.createElement(E.default,(0,w.default)({className:s,style:l,listType:"card",closable:!0,locale:i,value:this.state.value,onRemove:d,onCancel:f,onPreview:c,itemRender:g,isPreview:h,uploader:this.uploaderRef,reUpload:y,showDownload:n},_),M.default.createElement(x.default,(0,w.default)({},b,{shape:"card",prefix:o,disabled:r,action:a,timeout:p,isPreview:h,value:this.state.value,onProgress:this.onProgress,onChange:this.onChange,ref:function(e){return t.saveRef(e)},className:u}),v))},c=n=C,n.displayName="Card",n.propTypes={prefix:s.default.string,locale:s.default.object,children:s.default.object,value:s.default.oneOfType([s.default.array,s.default.object]),defaultValue:s.default.oneOfType([s.default.array,s.default.object]),onPreview:s.default.func,onChange:s.default.func,onRemove:s.default.func,onCancel:s.default.func,itemRender:s.default.func,reUpload:s.default.bool,showDownload:s.default.bool,onProgress:s.default.func,isPreview:s.default.bool,renderPreview:s.default.func},n.defaultProps={prefix:"next-",locale:u.default.Upload,showDownload:!0,onChange:S.func.noop,onPreview:S.func.noop,onProgress:S.func.noop},a=function(){var n=this;this.onProgress=function(e,t){n.setState({value:e}),n.props.onProgress(e,t)},this.onChange=function(e,t){"value"in n.props||n.setState({value:e}),n.props.onChange(e,t)}};var f,i=c;function C(e){(0,r.default)(this,C);var t=(0,o.default)(this,f.call(this,e)),n=(a.call(t),void 0),n="value"in e?e.value:e.defaultValue;return t.state={value:Array.isArray(n)?n:[],uploaderRef:t.uploaderRef},t}t.default=(0,l.polyfill)(i),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var u=m(n(3)),c=m(n(16)),o=m(n(4)),i=m(n(7)),a=m(n(8)),d=m(n(0)),r=m(n(5)),f=m(n(18)),p=m(n(26)),s=n(11),l=m(n(44)),h=m(n(193));function m(e){return e&&e.__esModule?e:{default:e}}g=d.default.Component,(0,a.default)(y,g),y.prototype.abort=function(e){this.uploaderRef.abort(e)},y.prototype.startUpload=function(){this.uploaderRef.startUpload()},y.prototype.render=function(){var e=this.props,t=e.className,n=e.style,a=e.shape,r=e.locale,o=e.prefix,i=e.listType,e=(0,c.default)(e,["className","style","shape","locale","prefix","listType"]),s=o+"upload-drag",t=(0,f.default)(((l={})[s]=!0,l[s+"-over"]=this.state.dragOver,l[t]=!!t,l)),l=this.props.children||d.default.createElement("div",{className:t},d.default.createElement("p",{className:s+"-icon"},d.default.createElement(p.default,{size:"large",className:s+"-upload-icon"})),d.default.createElement("p",{className:s+"-text"},r.drag.text),d.default.createElement("p",{className:s+"-hint"},r.drag.hint));return d.default.createElement(h.default,(0,u.default)({},e,{prefix:o,shape:a,listType:i,dragable:!0,style:n,onDragOver:this.onDragOver,onDragLeave:this.onDragLeave,onDrop:this.onDrop,ref:this.saveUploaderRef}),l)},a=n=y,n.propTypes={prefix:r.default.string,locale:r.default.object,shape:r.default.string,onDragOver:r.default.func,onDragLeave:r.default.func,onDrop:r.default.func,limit:r.default.number,className:r.default.string,style:r.default.object,defaultValue:r.default.array,children:r.default.node,listType:r.default.string,timeout:r.default.number},n.defaultProps={prefix:"next-",onDragOver:s.func.noop,onDragLeave:s.func.noop,onDrop:s.func.noop,locale:l.default.Upload};var g,r=a;function y(){var e,t;(0,o.default)(this,y);for(var n=arguments.length,a=Array(n),r=0;r>1,c=-7,d=n?r-1:0,f=n?-1:1,r=e[t+d];for(d+=f,o=r&(1<<-c)-1,r>>=-c,c+=s;0>=-c,c+=a;0>1,d=23===r?Math.pow(2,-24)-Math.pow(2,-77):0,f=a?0:o-1,p=a?1:-1,o=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,i=u):(i=Math.floor(Math.log(t)/Math.LN2),t*(a=Math.pow(2,-i))<1&&(i--,a*=2),2<=(t+=1<=i+c?d/a:d*Math.pow(2,1-c))*a&&(i++,a/=2),u<=i+c?(s=0,i=u):1<=i+c?(s=(t*a-1)*Math.pow(2,r),i+=c):(s=t*Math.pow(2,c-1)*Math.pow(2,r),i=0));8<=r;e[n+f]=255&s,f+=p,s/=256,r-=8);for(i=i<>>0),r=this.head,o=0;r;)t=r.data,n=o,t.copy(a,n),o+=r.data.length,r=r.next;return a},r),a&&a.inspect&&a.inspect.custom&&(e.exports.prototype[a.inspect.custom]=function(){var e=a.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){!function(t){function a(e){try{if(!t.localStorage)return}catch(e){return}e=t.localStorage[e];return null!=e&&"true"===String(e).toLowerCase()}e.exports=function(e,t){if(a("noDeprecation"))return e;var n=!1;return function(){if(!n){if(a("throwDeprecation"))throw new Error(t);a("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}}}.call(this,n(65))},function(e,t,n){"use strict";e.exports=r;var a=n(418),e=Object.create(n(118));function r(e){if(!(this instanceof r))return new r(e);a.call(this,e)}e.inherits=n(105),e.inherits(r,a),r.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){e.exports=n(190)},function(e,t,n){e.exports=n(92)},function(e,t,n){e.exports=n(189).Transform},function(e,t,n){e.exports=n(189).PassThrough},function(e,t,n){"use strict";function u(e){return new Error("Can only stringify objects, not "+e)}function c(t){return Object.keys(t).filter(e=>p(t[e]))}function d(e){var t,n=Array.isArray(e)?[]:Object.prototype.hasOwnProperty.call(e,"__proto__")?{["__proto__"]:void 0}:{};for(t of Object.keys(e))!e[t]||"function"!=typeof e[t].toJSON||"toISOString"in e[t]?n[t]=e[t]:n[t]=e[t].toJSON();return n}function f(t,e,n){var a,r,o=c(n=d(n));r=n,a=Object.keys(r).filter(e=>!p(r[e]));const i=[],s=e||"",l=(o.forEach(e=>{var t=h(n[e]);"undefined"!==t&&"null"!==t&&i.push(s+m(e)+" = "+g(n[e],!0))}),0{i.push(function(e,t,n,a){var r=h(a);{if("array"===r)return function(e,t,n,a){var r=h((a=d(a))[0]);if("table"!==r)throw u(r);const o=e+m(n);let i="";return a.forEach(e=>{0"\\u"+function(e,t){for(;t.lengths(e).replace(/"(?="")/g,'\\"')).join("\n");return'"'===e.slice(-1)&&(e+="\\\n"),'"""\n'+e+'"""';return}case"string":return i(t);case"string-literal":return"'"+t+"'";case"integer":return y(t);case"float":n=t;return n===1/0?"inf":n===-1/0?"-inf":Object.is(n,NaN)?"nan":Object.is(n,-0)?"-0.0":([n,a]=String(n).split("."),y(n)+"."+a);case"boolean":return String(t);case"datetime":return t.toISOString();case"array":{var a=t.filter(e=>"null"!==h(e)&&"undefined"!==h(e)&&"nan"!==h(e));a=d(a);let e="[";a=a.map(e=>l(e));60{o.push(m(e)+" = "+g(r[e],!1))}),"{ "+o.join(", ")+(0=P.KEYCODE.LEFT&&t<=P.KEYCODE.DOWN&&e.preventDefault(),e=void 0,t===P.KEYCODE.RIGHT||t===P.KEYCODE.DOWN?(e=o.getNextActiveKey(!0),o.handleTriggerEvent(o.props.triggerType,e)):t!==P.KEYCODE.LEFT&&t!==P.KEYCODE.UP||(e=o.getNextActiveKey(!1),o.handleTriggerEvent(o.props.triggerType,e)))},o.state={activeKey:o.getDefaultActiveKey(e)},o}s.displayName="Tab",t.default=(0,l.polyfill)(s),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var _=d(n(3)),a=d(n(4)),r=d(n(7)),o=d(n(8)),b=d(n(0)),i=n(25),s=d(n(5)),w=d(n(19)),M=d(n(26)),l=d(n(64)),u=d(n(50)),k=(d(n(20)),d(n(83))),h=n(11),c=n(420);function d(e){return e&&e.__esModule?e:{default:e}}var f,S={float:"right",zIndex:1},E={float:"left",zIndex:1},p={dropdown:"arrow-down",prev:"arrow-left",next:"arrow-right"},m=l.default.Popup,l=(f=b.default.Component,(0,o.default)(g,f),g.prototype.componentDidMount=function(){this.props.animation||this.initialSettings(),h.events.on(window,"resize",this.onWindowResized)},g.prototype.componentDidUpdate=function(e){var t=this;clearTimeout(this.scrollTimer),this.scrollTimer=setTimeout(function(){t.scrollToActiveTab()},410),clearTimeout(this.slideTimer),this.slideTimer=setTimeout(function(){t.setSlideBtn()},410),"dropdown"!==this.props.excessMode||(0,c.tabsArrayShallowEqual)(this.props.tabs,e.tabs)||this.getDropdownItems(this.props)},g.prototype.componentWillUnmount=function(){h.events.off(window,"resize",this.onWindowResized)},g.prototype.initialSettings=function(){this.setSlideBtn(),this.getDropdownItems(this.props)},g.prototype.setOffset=function(e){var t=!(1n&&(t.current=n),this.setState(t),this.props.onPageSizeChange(e)},I.prototype.renderPageTotal=function(){var e=this.props,t=e.prefix,n=e.total,e=e.totalRender,a=this.state,r=a.currentPageSize,a=a.current;return N.default.createElement("div",{className:t+"pagination-total"},e(n,[(a-1)*r+1,a*r]))},I.prototype.renderPageItem=function(e){var t=this.props,n=t.prefix,a=t.size,r=t.link,o=t.pageNumberRender,i=t.total,s=t.pageSize,t=t.locale,l=this.state.current,i=Y(i,s),s=parseInt(e,10)===l,a={size:a,className:(0,P.default)(((l={})[n+"pagination-item"]=!0,l[n+"current"]=s,l)),onClick:s?m:this.onPageItemClick.bind(this,e)};return r&&(a.component="a",a.href=r.replace("{page}",e)),N.default.createElement(d.default,(0,D.default)({"aria-label":j.str.template(t.total,{current:e,total:i})},a,{key:e}),o(e))},I.prototype.renderPageFirst=function(e){var t=this.props,n=t.prefix,a=t.size,r=t.shape,t=t.locale,a={disabled:e<=1,size:a,className:(0,P.default)(((a={})[n+"pagination-item"]=!0,a[n+"prev"]=!0,a)),onClick:this.onPageItemClick.bind(this,e-1)},n=N.default.createElement(c.default,{type:"arrow-left",className:n+"pagination-icon-prev"});return N.default.createElement(d.default,(0,D.default)({},a,{"aria-label":j.str.template(t.labelPrev,{current:e})}),n,"arrow-only"===r||"arrow-prev-only"===r||"no-border"===r?"":t.prev)},I.prototype.renderPageLast=function(e,t){var n=this.props,a=n.prefix,r=n.size,o=n.shape,n=n.locale,r={disabled:t<=e,size:r,className:(0,P.default)(((t={})[a+"pagination-item"]=!0,t[a+"next"]=!0,t)),onClick:this.onPageItemClick.bind(this,e+1)},t=N.default.createElement(c.default,{type:"arrow-right",className:a+"pagination-icon-next"});return N.default.createElement(d.default,(0,D.default)({},r,{"aria-label":j.str.template(n.labelNext,{current:e})}),"arrow-only"===o||"no-border"===o?"":n.next,t)},I.prototype.renderPageEllipsis=function(e){var t=this.props.prefix;return N.default.createElement(c.default,{className:t+"pagination-ellipsis "+t+"pagination-icon-ellipsis",type:"ellipsis",key:"ellipsis-"+e})},I.prototype.renderPageJump=function(){var t=this,e=this.props,n=e.prefix,a=e.size,e=e.locale,r=this.state.inputValue;return[N.default.createElement("span",{className:n+"pagination-jump-text"},e.goTo),N.default.createElement(f.default,{className:n+"pagination-jump-input",type:"text","aria-label":e.inputAriaLabel,size:a,value:r,onChange:this.onInputChange.bind(this),onKeyDown:function(e){e.keyCode===j.KEYCODE.ENTER&&t.handleJump(e)}}),N.default.createElement("span",{className:n+"pagination-jump-text"},e.page),N.default.createElement(d.default,{className:n+"pagination-jump-go",size:a,onClick:this.handleJump},e.go)]},I.prototype.renderPageDisplay=function(e,t){var n=this.props,a=n.prefix,n=n.pageNumberRender;return N.default.createElement("span",{className:a+"pagination-display"},N.default.createElement("em",null,n(e)),"/",n(t))},I.prototype.renderPageList=function(e,t){var n=this.props,a=n.prefix,n=n.pageShowCount,r=[];if(t<=n)for(var o=1;o<=t;o++)r.push(this.renderPageItem(o));else{var n=n-3,i=parseInt(n/2,10),s=void 0,l=void 0;r.push(this.renderPageItem(1)),l=e+i,(s=e-i)<=1&&(l=(s=2)+n),2=e.length&&-1=this.props.children.length?(this.update(this.props),this.changeSlide({message:"index",index:this.props.children.length-this.props.slidesToShow,currentSlide:this.state.currentSlide})):(n=[],Object.keys(t).forEach(function(e){e in a.props&&t[e]!==a.props[e]&&n.push(e)}),1===n.length&&"children"===n[0]||l.obj.shallowEqual(t,this.props)||this.update(this.props)),this.adaptHeight()},p.prototype.componentWillUnmount=function(){this.animationEndCallback&&clearTimeout(this.animationEndCallback),l.events.off(window,"resize",this.onWindowResized),this.state.autoPlayTimer&&clearInterval(this.state.autoPlayTimer)},p.prototype.onWindowResized=function(){this.update(this.props),this.setState({animating:!1}),clearTimeout(this.animationEndCallback),delete this.animationEndCallback},p.prototype.slickGoTo=function(e){"number"==typeof e&&this.changeSlide({message:"index",index:e,currentSlide:this.state.currentSlide})},p.prototype.onEnterArrow=function(e){this.arrowHoverHandler(e)},p.prototype.onLeaveArrow=function(){this.arrowHoverHandler()},p.prototype._instanceRefHandler=function(e,t){this[e]=t},p.prototype.render=function(){var e=this.props,t=e.prefix,n=e.animation,a=e.arrows,r=e.arrowSize,o=e.arrowPosition,i=e.arrowDirection,s=e.dots,l=e.dotsClass,u=e.cssEase,c=e.speed,d=e.infinite,f=e.centerMode,p=e.centerPadding,h=e.lazyLoad,m=e.dotsDirection,g=e.rtl,y=e.slidesToShow,v=e.slidesToScroll,_=e.variableWidth,b=e.vertical,w=e.verticalSwiping,M=e.focusOnSelect,k=e.children,S=e.dotsRender,e=e.triggerType,E=this.state,x=E.currentSlide,C=E.lazyLoadedList,T=E.slideCount,L=E.slideWidth,O=E.slideHeight,D=E.trackStyle,N=E.listHeight,E=E.dragging,u={prefix:t,animation:n,cssEase:u,speed:c,infinite:d,centerMode:f,focusOnSelect:M?this.selectHandler:null,currentSlide:x,lazyLoad:h,lazyLoadedList:C,rtl:g,slideWidth:L,slideHeight:O,slidesToShow:y,slidesToScroll:v,slideCount:T,trackStyle:D,variableWidth:_,vertical:b,verticalSwiping:w,triggerType:e},c=void 0,h=(!0===s&&yt.startX?1:-1),!0===this.props.verticalSwiping&&(t.swipeLength=Math.round(Math.sqrt(Math.pow(t.curY-t.startY,2))),a=t.curY>t.startY?1:-1),r=this.state.currentSlide,s=Math.ceil(this.state.slideCount/this.props.slidesToScroll),o=this.swipeDirection(this.state.touchObject),i=t.swipeLength,!1===this.props.infinite&&(0===r&&"right"===o||s<=r+1&&"left"===o)&&(i=t.swipeLength*this.props.edgeFriction,!1===this.state.edgeDragged)&&this.props.edgeEvent&&(this.props.edgeEvent(o),this.setState({edgeDragged:!0})),!1===this.state.swiped&&this.props.swipeEvent&&(this.props.swipeEvent(o),this.setState({swiped:!0})),this.setState({touchObject:t,swipeLeft:s=n+i*a,trackStyle:(0,u.getTrackCSS)((0,l.default)({left:s},this.props,this.state))}),Math.abs(t.curX-t.startX)<.8*Math.abs(t.curY-t.startY))||4t[t.length-1])e=t[t.length-1];else for(var a in t){if(e-1*n.state.swipeLeft)return t=e,!1}else if(e.offsetLeft-a+(n.getWidth(e)||0)/2>-1*n.state.swipeLeft)return t=e,!1;return!0}),Math.abs(t.dataset.index-this.state.currentSlide)||1):this.props.slidesToScroll},swipeEnd:function(e){if(this.state.dragging){var t=this.state.touchObject,n=this.state.listWidth/this.props.touchThreshold,a=this.swipeDirection(t);if(this.props.verticalSwiping&&(n=this.state.listHeight/this.props.touchThreshold),this.setState({dragging:!1,edgeDragged:!1,swiped:!1,swipeLeft:null,touchObject:{}}),t.swipeLength)if(t.swipeLength>n){e.preventDefault();var r=void 0,o=void 0;switch(a){case"left":case"down":o=this.state.currentSlide+this.getSlideCount(),r=this.props.swipeToSlide?this.checkNavigable(o):o,this.setState({currentDirection:0});break;case"right":case"up":o=this.state.currentSlide-this.getSlideCount(),r=this.props.swipeToSlide?this.checkNavigable(o):o,this.setState({currentDirection:1});break;default:r=this.state.currentSlide}this.slideHandler(r)}else{t=(0,u.getTrackLeft)((0,l.default)({slideIndex:this.state.currentSlide,trackRef:this.track},this.props,this.state));this.setState({trackStyle:(0,u.getTrackAnimateCSS)((0,l.default)({left:t},this.props,this.state))})}}else this.props.swipe&&e.preventDefault()},onInnerSliderEnter:function(){this.props.autoplay&&this.props.pauseOnHover&&this.pause()},onInnerSliderLeave:function(){this.props.autoplay&&this.props.pauseOnHover&&this.autoPlay()}},e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var g=a(n(3)),c=a(n(0)),d=a(n(25)),y=n(423);function a(e){return e&&e.__esModule?e:{default:e}}t.default={initialize:function(t){var n=this,e=d.default.findDOMNode(this.list),a=c.default.Children.count(t.children),r=this.getWidth(e)||0,o=this.getWidth(d.default.findDOMNode(this.track))||0,i=void 0,e=(i=t.vertical?r:(r-(t.centerMode&&2*parseInt(t.centerPadding)))/t.slidesToShow,this.getHeight(e.querySelector('[data-index="0"]'))||0),s=e*t.slidesToShow,l=t.slidesToShow||1,u="activeIndex"in t?t.activeIndex:t.defaultActiveIndex,l=t.rtl?a-1-(l-1)-u:u;this.setState({slideCount:a,slideWidth:i,listWidth:r,trackWidth:o,currentSlide:l,slideHeight:e,listHeight:s},function(){var e=(0,y.getTrackLeft)((0,g.default)({slideIndex:n.state.currentSlide,trackRef:n.track},t,n.state)),e=(0,y.getTrackCSS)((0,g.default)({left:e},t,n.state));n.setState({trackStyle:e}),n.autoPlay()})},update:function(e){this.initialize(e)},getWidth:function(e){return"clientWidth"in e?e.clientWidth:e&&e.getBoundingClientRect().width},getHeight:function(e){return"clientHeight"in e?e.clientHeight:e&&e.getBoundingClientRect().height},adaptHeight:function(){var e,t;this.props.adaptiveHeight&&(t='[data-index="'+this.state.currentSlide+'"]',this.list)&&(t=(e=d.default.findDOMNode(this.list)).querySelector(t).offsetHeight,e.style.height=t+"px")},canGoNext:function(e){var t=!0;return e.infinite||(e.centerMode?e.currentSlide>=e.slideCount-1&&(t=!1):(e.slideCount<=e.slidesToShow||e.currentSlide>=e.slideCount-e.slidesToShow)&&(t=!1)),t},slideHandler:function(e){var t=this,n=this.props.rtl,a=void 0,r=void 0,o=void 0;if(!this.props.waitForAnimate||!this.state.animating){if("fade"===this.props.animation)return r=this.state.currentSlide,!1===this.props.infinite&&(e<0||e>=this.state.slideCount)?void 0:(a=e<0?e+this.state.slideCount:e>=this.state.slideCount?e-this.state.slideCount:e,this.props.lazyLoad&&this.state.lazyLoadedList.indexOf(a)<0&&this.setState({lazyLoadedList:this.state.lazyLoadedList.concat(a)}),o=function(){t.setState({animating:!1}),t.props.onChange(a),delete t.animationEndCallback},this.props.onBeforeChange(this.state.currentSlide,a),this.setState({animating:!0,currentSlide:a},function(){this.animationEndCallback=setTimeout(o,this.props.speed+20)}),void this.autoPlay());a=e,n?a<0?!1===this.props.infinite?r=0:this.state.slideCount%this.props.slidesToScroll!=0?a+this.props.slidesToScroll<=0?(r=this.state.slideCount+a,a=this.state.slideCount-this.props.slidesToScroll):r=a=0:r=this.state.slideCount+a:r=a>=this.state.slideCount?!1===this.props.infinite?this.state.slideCount-this.props.slidesToShow:this.state.slideCount%this.props.slidesToScroll!=0?0:a-this.state.slideCount:a:r=a<0?!1===this.props.infinite?0:this.state.slideCount%this.props.slidesToScroll!=0?this.state.slideCount-this.state.slideCount%this.props.slidesToScroll:this.state.slideCount+a:a>=this.state.slideCount?!1===this.props.infinite?this.state.slideCount-this.props.slidesToShow:this.state.slideCount%this.props.slidesToScroll!=0?0:a-this.state.slideCount:a;var i,e=(0,y.getTrackLeft)((0,g.default)({slideIndex:a,trackRef:this.track},this.props,this.state)),s=(0,y.getTrackLeft)((0,g.default)({slideIndex:r,trackRef:this.track},this.props,this.state));if(!1===this.props.infinite&&(e=s),this.props.lazyLoad){for(var l=!0,u=[],c=this.state.slideCount,d=a<0?c+a:r,f=d;f=l.activeIndex?"visible":"hidden",c.transition="opacity "+l.speed+"ms "+l.cssEase,c.WebkitTransition="opacity "+l.speed+"ms "+l.cssEase,l.vertical?c.top=-l.activeIndex*l.slideHeight:c.left=-l.activeIndex*l.slideWidth),l.vertical&&(c.width="100%"),c),u=(c=(0,v.default)({activeIndex:e},d),a=c.prefix,u=r=i=void 0,o=(u=c.rtl?c.slideCount-1-c.activeIndex:c.activeIndex)<0||u>=c.slideCount,c.centerMode?(n=Math.floor(c.slidesToShow/2),r=(u-c.currentSlide)%c.slideCount==0,u>c.currentSlide-n-1&&u<=c.currentSlide+n&&(i=!0)):i=c.currentSlide<=u&&u=u,u=(0,k.default)(((v={})[o+"upload-list-item"]=!0,v[o+"hidden"]=u,v)),v=this.props.children||i.card.addPhoto,d=r?S.func.prevent:d,_=S.obj.pickOthers(C.propTypes,this.props),b=S.obj.pickOthers(E.default.propTypes,_);if(h&&"function"==typeof m)return e=(0,k.default)(((e={})[o+"form-preview"]=!0,e[s]=!!s,e)),M.default.createElement("div",{style:l,className:e},m(this.state.value,this.props));return M.default.createElement(E.default,(0,w.default)({className:s,style:l,listType:"card",closable:!0,locale:i,value:this.state.value,onRemove:d,onCancel:f,onPreview:c,itemRender:g,isPreview:h,uploader:this.uploaderRef,reUpload:y,showDownload:n},_),M.default.createElement(x.default,(0,w.default)({},b,{shape:"card",prefix:o,disabled:r,action:a,timeout:p,isPreview:h,value:this.state.value,onProgress:this.onProgress,onChange:this.onChange,ref:function(e){return t.saveRef(e)},className:u}),v))},c=n=C,n.displayName="Card",n.propTypes={prefix:s.default.string,locale:s.default.object,children:s.default.object,value:s.default.oneOfType([s.default.array,s.default.object]),defaultValue:s.default.oneOfType([s.default.array,s.default.object]),onPreview:s.default.func,onChange:s.default.func,onRemove:s.default.func,onCancel:s.default.func,itemRender:s.default.func,reUpload:s.default.bool,showDownload:s.default.bool,onProgress:s.default.func,isPreview:s.default.bool,renderPreview:s.default.func},n.defaultProps={prefix:"next-",locale:u.default.Upload,showDownload:!0,onChange:S.func.noop,onPreview:S.func.noop,onProgress:S.func.noop},a=function(){var n=this;this.onProgress=function(e,t){n.setState({value:e}),n.props.onProgress(e,t)},this.onChange=function(e,t){"value"in n.props||n.setState({value:e}),n.props.onChange(e,t)}};var f,i=c;function C(e){(0,r.default)(this,C);var t=(0,o.default)(this,f.call(this,e)),n=(a.call(t),void 0),n="value"in e?e.value:e.defaultValue;return t.state={value:Array.isArray(n)?n:[],uploaderRef:t.uploaderRef},t}t.default=(0,l.polyfill)(i),e.exports=t.default},function(e,t,n){"use strict";t.__esModule=!0;var u=m(n(3)),c=m(n(17)),o=m(n(4)),i=m(n(7)),a=m(n(8)),d=m(n(0)),r=m(n(5)),f=m(n(19)),p=m(n(26)),s=n(11),l=m(n(44)),h=m(n(193));function m(e){return e&&e.__esModule?e:{default:e}}g=d.default.Component,(0,a.default)(y,g),y.prototype.abort=function(e){this.uploaderRef.abort(e)},y.prototype.startUpload=function(){this.uploaderRef.startUpload()},y.prototype.render=function(){var e=this.props,t=e.className,n=e.style,a=e.shape,r=e.locale,o=e.prefix,i=e.listType,e=(0,c.default)(e,["className","style","shape","locale","prefix","listType"]),s=o+"upload-drag",t=(0,f.default)(((l={})[s]=!0,l[s+"-over"]=this.state.dragOver,l[t]=!!t,l)),l=this.props.children||d.default.createElement("div",{className:t},d.default.createElement("p",{className:s+"-icon"},d.default.createElement(p.default,{size:"large",className:s+"-upload-icon"})),d.default.createElement("p",{className:s+"-text"},r.drag.text),d.default.createElement("p",{className:s+"-hint"},r.drag.hint));return d.default.createElement(h.default,(0,u.default)({},e,{prefix:o,shape:a,listType:i,dragable:!0,style:n,onDragOver:this.onDragOver,onDragLeave:this.onDragLeave,onDrop:this.onDrop,ref:this.saveUploaderRef}),l)},a=n=y,n.propTypes={prefix:r.default.string,locale:r.default.object,shape:r.default.string,onDragOver:r.default.func,onDragLeave:r.default.func,onDrop:r.default.func,limit:r.default.number,className:r.default.string,style:r.default.object,defaultValue:r.default.array,children:r.default.node,listType:r.default.string,timeout:r.default.number},n.defaultProps={prefix:"next-",onDragOver:s.func.noop,onDragLeave:s.func.noop,onDrop:s.func.noop,locale:l.default.Upload};var g,r=a;function y(){var e,t;(0,o.default)(this,y);for(var n=arguments.length,a=Array(n),r=0;r getNamespaceList() { // TODO 获取用kp List tenantInfos = namespacePersistService.findTenantByKp(DEFAULT_KP); - Namespace namespace0 = new Namespace(NamespaceUtil.getNamespaceDefaultId(), DEFAULT_NAMESPACE, DEFAULT_QUOTA, 0, - NamespaceTypeEnum.GLOBAL.getType()); + Namespace namespace0 = new Namespace(NamespaceUtil.getNamespaceDefaultId(), DEFAULT_NAMESPACE_SHOW_NAME, + DEFAULT_NAMESPACE_DESCRIPTION, DEFAULT_QUOTA, 0, NamespaceTypeEnum.GLOBAL.getType()); NamespaceDetailInjectorHolder.getInstance().injectDetail(namespace0); List namespaceList = new ArrayList<>(); namespaceList.add(namespace0); diff --git a/core/src/test/java/com/alibaba/nacos/core/cluster/remote/ClusterRpcClientProxyTest.java b/core/src/test/java/com/alibaba/nacos/core/cluster/remote/ClusterRpcClientProxyTest.java index dfbbea95e72..80deadb76bc 100644 --- a/core/src/test/java/com/alibaba/nacos/core/cluster/remote/ClusterRpcClientProxyTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/cluster/remote/ClusterRpcClientProxyTest.java @@ -23,6 +23,7 @@ import com.alibaba.nacos.api.remote.ability.ServerRemoteAbility; import com.alibaba.nacos.api.remote.request.HealthCheckRequest; import com.alibaba.nacos.api.remote.response.Response; +import com.alibaba.nacos.auth.config.AuthConfigs; import com.alibaba.nacos.common.remote.ConnectionType; import com.alibaba.nacos.common.remote.client.RpcClient; import com.alibaba.nacos.common.remote.client.RpcClientFactory; @@ -69,6 +70,9 @@ class ClusterRpcClientProxyTest { @Mock private ServerMemberManager serverMemberManager; + @Mock + private AuthConfigs authConfigs; + @Mock private RpcClient client; @@ -96,6 +100,8 @@ void setUp() throws NacosException { clientMap.remove("Cluster-" + member.getAddress()).shutdown(); clientMap.put("Cluster-" + member.getAddress(), client); when(client.getConnectionType()).thenReturn(ConnectionType.GRPC); + when(authConfigs.getServerIdentityKey()).thenReturn("MockIdentityKey"); + when(authConfigs.getServerIdentityValue()).thenReturn("MockIdentityValue"); } @Test diff --git a/core/src/test/java/com/alibaba/nacos/core/service/NamespaceOperationServiceTest.java b/core/src/test/java/com/alibaba/nacos/core/service/NamespaceOperationServiceTest.java index 6cb70e825bb..e8ccd86bb13 100644 --- a/core/src/test/java/com/alibaba/nacos/core/service/NamespaceOperationServiceTest.java +++ b/core/src/test/java/com/alibaba/nacos/core/service/NamespaceOperationServiceTest.java @@ -57,7 +57,9 @@ class NamespaceOperationServiceTest { private static final String TEST_NAMESPACE_DESC = "testDesc"; - private static final String DEFAULT_NAMESPACE = "public"; + private static final String DEFAULT_NAMESPACE_SHOW_NAME = "public"; + + private static final String DEFAULT_NAMESPACE_DESCRIPTION = "Default Namespace"; private static final int DEFAULT_QUOTA = 200; @@ -93,7 +95,8 @@ void testGetNamespaceList() { assertEquals(2, list.size()); Namespace namespaceA = list.get(0); assertEquals("", namespaceA.getNamespace()); - assertEquals(DEFAULT_NAMESPACE, namespaceA.getNamespaceShowName()); + assertEquals(DEFAULT_NAMESPACE_SHOW_NAME, namespaceA.getNamespaceShowName()); + assertEquals(DEFAULT_NAMESPACE_DESCRIPTION, namespaceA.getNamespaceDesc()); assertEquals(DEFAULT_QUOTA, namespaceA.getQuota()); assertEquals(1, namespaceA.getConfigCount()); @@ -104,7 +107,7 @@ void testGetNamespaceList() { } @Test - void testGetNamespace() throws NacosException { + void testGetNamespace() { assertThrows(NacosApiException.class, () -> { TenantInfo tenantInfo = new TenantInfo(); diff --git a/distribution/conf/application.properties b/distribution/conf/application.properties index 10db6262f92..43ca20394ea 100644 --- a/distribution/conf/application.properties +++ b/distribution/conf/application.properties @@ -40,7 +40,7 @@ server.port=8848 # db.num=1 ### Connect URL of DB: -# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC +# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai # db.user.0=nacos # db.password.0=nacos diff --git a/distribution/conf/application.properties.example b/distribution/conf/application.properties.example index 93d18af2233..0fc781decfd 100644 --- a/distribution/conf/application.properties.example +++ b/distribution/conf/application.properties.example @@ -40,7 +40,7 @@ server.port=8848 # db.num=1 ### Connect URL of DB: -# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC +# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai # db.user.0=nacos # db.password.0=nacos diff --git a/distribution/conf/derby-schema.sql b/distribution/conf/derby-schema.sql index f4e93a3aab6..6a2392369ca 100644 --- a/distribution/conf/derby-schema.sql +++ b/distribution/conf/derby-schema.sql @@ -17,46 +17,48 @@ CREATE SCHEMA nacos AUTHORIZATION nacos; CREATE TABLE config_info ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128) DEFAULT NULL, - src_ip varchar(50) DEFAULT NULL, - c_desc varchar(256) DEFAULT NULL, - c_use varchar(64) DEFAULT NULL, - effect varchar(64) DEFAULT NULL, - type varchar(64) DEFAULT NULL, - c_schema LONG VARCHAR DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint configinfo_id_key PRIMARY KEY (id), - constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128) DEFAULT NULL, + src_ip varchar(50) DEFAULT NULL, + c_desc varchar(256) DEFAULT NULL, + c_use varchar(64) DEFAULT NULL, + effect varchar(64) DEFAULT NULL, + type varchar(64) DEFAULT NULL, + c_schema LONG VARCHAR DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfo_id_key PRIMARY KEY (id), + constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); CREATE INDEX configinfo_dataid_key_idx ON config_info(data_id); CREATE INDEX configinfo_groupid_key_idx ON config_info(group_id); CREATE INDEX configinfo_dataid_group_key_idx ON config_info(data_id, group_id); CREATE TABLE his_config_info ( - id bigint NOT NULL, - nid bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - op_type char(10) DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); + id bigint NOT NULL, + nid bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + publish_type varchar(50) DEFAULT 'formal', + ext_info CLOB, + op_type char(10) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); CREATE INDEX hisconfiginfo_dataid_key_idx ON his_config_info(data_id); CREATE INDEX hisconfiginfo_gmt_create_idx ON his_config_info(gmt_create); @@ -64,164 +66,174 @@ CREATE INDEX hisconfiginfo_gmt_modified_idx ON his_config_info(gmt_modified); CREATE TABLE config_info_beta ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - beta_ips varchar(1024), - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint configinfobeta_id_key PRIMARY KEY (id), - constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + beta_ips varchar(1024), + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfobeta_id_key PRIMARY KEY (id), + constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); CREATE TABLE config_info_tag ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - tag_id varchar(128) NOT NULL, - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - constraint configinfotag_id_key PRIMARY KEY (id), - constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); - -CREATE TABLE config_info_aggr ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - datum_id varchar(255) NOT NULL, - app_name varchar(128), - content CLOB, - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - constraint configinfoaggr_id_key PRIMARY KEY (id), - constraint uk_configinfoaggr_datagrouptenantdatum UNIQUE (data_id,group_id,tenant_id,datum_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + tag_id varchar(128) NOT NULL, + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + constraint configinfotag_id_key PRIMARY KEY (id), + constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); + +CREATE TABLE config_info_gray ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + gray_name varchar(128) NOT NULL, + gray_rule CLOB, + app_name varchar(128), + src_ip varchar(128), + src_user varchar(128) default '', + content CLOB, + md5 varchar(32) DEFAULT NULL, + encrypted_data_key varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + constraint configinfogray_id_key PRIMARY KEY (id), + constraint uk_configinfogray_datagrouptenantgrayname UNIQUE (data_id,group_id,tenant_id,gray_name)); +CREATE INDEX config_info_gray_dataid_gmt_modified ON config_info_gray(data_id,gmt_modified); +CREATE INDEX config_info_gray_gmt_modified ON config_info_gray(gmt_modified); CREATE TABLE app_list ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - is_dynamic_collect_disabled smallint DEFAULT 0, - last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', - sub_info_lock_owner varchar(128), - sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', - constraint applist_id_key PRIMARY KEY (id), - constraint uk_appname UNIQUE (app_name)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + is_dynamic_collect_disabled smallint DEFAULT 0, + last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', + sub_info_lock_owner varchar(128), + sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', + constraint applist_id_key PRIMARY KEY (id), + constraint uk_appname UNIQUE (app_name)); CREATE TABLE app_configdata_relation_subs ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint configdatarelationsubs_id_key PRIMARY KEY (id), - constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationsubs_id_key PRIMARY KEY (id), + constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); CREATE TABLE app_configdata_relation_pubs ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint configdatarelationpubs_id_key PRIMARY KEY (id), - constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationpubs_id_key PRIMARY KEY (id), + constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); CREATE TABLE config_tags_relation ( - id bigint NOT NULL, - tag_name varchar(128) NOT NULL, - tag_type varchar(64) DEFAULT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) DEFAULT '', - nid bigint NOT NULL generated by default as identity, - constraint config_tags_id_key PRIMARY KEY (nid), - constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); + id bigint NOT NULL, + tag_name varchar(128) NOT NULL, + tag_type varchar(64) DEFAULT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + nid bigint NOT NULL generated by default as identity, + constraint config_tags_id_key PRIMARY KEY (nid), + constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); CREATE INDEX config_tags_tenant_id_idx ON config_tags_relation(tenant_id); CREATE TABLE group_capacity ( - id bigint NOT NULL generated by default as identity, - group_id varchar(128) DEFAULT '', - quota int DEFAULT 0, - usage int DEFAULT 0, - max_size int DEFAULT 0, - max_aggr_count int DEFAULT 0, - max_aggr_size int DEFAULT 0, - max_history_count int DEFAULT 0, - gmt_create timestamp DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint group_capacity_id_key PRIMARY KEY (id), - constraint uk_group_id UNIQUE (group_id)); + id bigint NOT NULL generated by default as identity, + group_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint group_capacity_id_key PRIMARY KEY (id), + constraint uk_group_id UNIQUE (group_id)); CREATE TABLE tenant_capacity ( - id bigint NOT NULL generated by default as identity, - tenant_id varchar(128) DEFAULT '', - quota int DEFAULT 0, - usage int DEFAULT 0, - max_size int DEFAULT 0, - max_aggr_count int DEFAULT 0, - max_aggr_size int DEFAULT 0, - max_history_count int DEFAULT 0, - gmt_create timestamp DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint tenant_capacity_id_key PRIMARY KEY (id), - constraint uk_tenant_id UNIQUE (tenant_id)); + id bigint NOT NULL generated by default as identity, + tenant_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint tenant_capacity_id_key PRIMARY KEY (id), + constraint uk_tenant_id UNIQUE (tenant_id)); CREATE TABLE tenant_info ( - id bigint NOT NULL generated by default as identity, - kp varchar(128) NOT NULL, - tenant_id varchar(128) DEFAULT '', - tenant_name varchar(128) DEFAULT '', - tenant_desc varchar(256) DEFAULT NULL, - create_source varchar(32) DEFAULT NULL, - gmt_create bigint NOT NULL, - gmt_modified bigint NOT NULL, - constraint tenant_info_id_key PRIMARY KEY (id), - constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); + id bigint NOT NULL generated by default as identity, + kp varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + tenant_name varchar(128) DEFAULT '', + tenant_desc varchar(256) DEFAULT NULL, + create_source varchar(32) DEFAULT NULL, + gmt_create bigint NOT NULL, + gmt_modified bigint NOT NULL, + constraint tenant_info_id_key PRIMARY KEY (id), + constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id); CREATE TABLE users ( - username varchar(50) NOT NULL PRIMARY KEY, - password varchar(500) NOT NULL, - enabled boolean NOT NULL DEFAULT true + username varchar(50) NOT NULL PRIMARY KEY, + password varchar(500) NOT NULL, + enabled boolean NOT NULL DEFAULT true ); CREATE TABLE roles ( - username varchar(50) NOT NULL, - role varchar(50) NOT NULL, - constraint uk_username_role UNIQUE (username,role) + username varchar(50) NOT NULL, + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) ); CREATE TABLE permissions ( - role varchar(50) NOT NULL, - resource varchar(512) NOT NULL, - action varchar(8) NOT NULL, - constraint uk_role_permission UNIQUE (role,resource,action) + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) ); + /******************************************/ /* ipv6 support */ /******************************************/ -ALTER TABLE `config_info_tag` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `his_config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL AFTER `src_user`; +ALTER TABLE config_info_tag ADD src_ip varchar(50) DEFAULT NULL; + +ALTER TABLE his_config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info_beta ADD src_ip varchar(50) DEFAULT NULL ; -ALTER TABLE `config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `config_info_beta` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; \ No newline at end of file +ALTER TABLE his_config_info ADD publish_type varchar(50) DEFAULT 'formal'; +ALTER TABLE his_config_info ADD ext_info CLOB DEFAULT NULL ; diff --git a/distribution/conf/mysql-schema.sql b/distribution/conf/mysql-schema.sql index d3c06606e13..770961904bf 100644 --- a/distribution/conf/mysql-schema.sql +++ b/distribution/conf/mysql-schema.sql @@ -18,141 +18,150 @@ /* 表名称 = config_info */ /******************************************/ CREATE TABLE `config_info` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', - `data_id` varchar(255) NOT NULL COMMENT 'data_id', - `group_id` varchar(128) DEFAULT NULL COMMENT 'group_id', - `content` longtext NOT NULL COMMENT 'content', - `md5` varchar(32) DEFAULT NULL COMMENT 'md5', - `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', - `src_user` text COMMENT 'source user', - `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', - `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', - `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', - `c_desc` varchar(256) DEFAULT NULL COMMENT 'configuration description', - `c_use` varchar(64) DEFAULT NULL COMMENT 'configuration usage', - `effect` varchar(64) DEFAULT NULL COMMENT '配置生效的描述', - `type` varchar(64) DEFAULT NULL COMMENT '配置的类型', - `c_schema` text COMMENT '配置的模式', - `encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) NOT NULL COMMENT 'data_id', + `group_id` varchar(128) DEFAULT NULL COMMENT 'group_id', + `content` longtext NOT NULL COMMENT 'content', + `md5` varchar(32) DEFAULT NULL COMMENT 'md5', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `src_user` text COMMENT 'source user', + `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', + `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', + `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', + `c_desc` varchar(256) DEFAULT NULL COMMENT 'configuration description', + `c_use` varchar(64) DEFAULT NULL COMMENT 'configuration usage', + `effect` varchar(64) DEFAULT NULL COMMENT '配置生效的描述', + `type` varchar(64) DEFAULT NULL COMMENT '配置的类型', + `c_schema` text COMMENT '配置的模式', + `encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info'; /******************************************/ -/* 表名称 = config_info_aggr */ -/******************************************/ -CREATE TABLE `config_info_aggr` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', - `data_id` varchar(255) NOT NULL COMMENT 'data_id', - `group_id` varchar(128) NOT NULL COMMENT 'group_id', - `datum_id` varchar(255) NOT NULL COMMENT 'datum_id', - `content` longtext NOT NULL COMMENT '内容', - `gmt_modified` datetime NOT NULL COMMENT '修改时间', - `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', - `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段'; - +/* 表名称 = config_info since 2.5.0 */ +/******************************************/ +CREATE TABLE `config_info_gray` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) NOT NULL COMMENT 'data_id', + `group_id` varchar(128) NOT NULL COMMENT 'group_id', + `content` longtext NOT NULL COMMENT 'content', + `md5` varchar(32) DEFAULT NULL COMMENT 'md5', + `src_user` text COMMENT 'src_user', + `src_ip` varchar(100) DEFAULT NULL COMMENT 'src_ip', + `gmt_create` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'gmt_create', + `gmt_modified` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'gmt_modified', + `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', + `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', + `gray_name` varchar(128) NOT NULL COMMENT 'gray_name', + `gray_rule` text NOT NULL COMMENT 'gray_rule', + `encrypted_data_key` varchar(256) NOT NULL DEFAULT '' COMMENT 'encrypted_data_key', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_configinfogray_datagrouptenantgray` (`data_id`,`group_id`,`tenant_id`,`gray_name`), + KEY `idx_dataid_gmt_modified` (`data_id`,`gmt_modified`), + KEY `idx_gmt_modified` (`gmt_modified`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='config_info_gray' /******************************************/ /* 表名称 = config_info_beta */ /******************************************/ CREATE TABLE `config_info_beta` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', - `data_id` varchar(255) NOT NULL COMMENT 'data_id', - `group_id` varchar(128) NOT NULL COMMENT 'group_id', - `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', - `content` longtext NOT NULL COMMENT 'content', - `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps', - `md5` varchar(32) DEFAULT NULL COMMENT 'md5', - `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', - `src_user` text COMMENT 'source user', - `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', - `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', - `encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) NOT NULL COMMENT 'data_id', + `group_id` varchar(128) NOT NULL COMMENT 'group_id', + `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', + `content` longtext NOT NULL COMMENT 'content', + `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps', + `md5` varchar(32) DEFAULT NULL COMMENT 'md5', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `src_user` text COMMENT 'source user', + `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', + `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', + `encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta'; /******************************************/ /* 表名称 = config_info_tag */ /******************************************/ CREATE TABLE `config_info_tag` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', - `data_id` varchar(255) NOT NULL COMMENT 'data_id', - `group_id` varchar(128) NOT NULL COMMENT 'group_id', - `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', - `tag_id` varchar(128) NOT NULL COMMENT 'tag_id', - `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', - `content` longtext NOT NULL COMMENT 'content', - `md5` varchar(32) DEFAULT NULL COMMENT 'md5', - `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', - `src_user` text COMMENT 'source user', - `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`) + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `data_id` varchar(255) NOT NULL COMMENT 'data_id', + `group_id` varchar(128) NOT NULL COMMENT 'group_id', + `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', + `tag_id` varchar(128) NOT NULL COMMENT 'tag_id', + `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', + `content` longtext NOT NULL COMMENT 'content', + `md5` varchar(32) DEFAULT NULL COMMENT 'md5', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `src_user` text COMMENT 'source user', + `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag'; /******************************************/ /* 表名称 = config_tags_relation */ /******************************************/ CREATE TABLE `config_tags_relation` ( - `id` bigint(20) NOT NULL COMMENT 'id', - `tag_name` varchar(128) NOT NULL COMMENT 'tag_name', - `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type', - `data_id` varchar(255) NOT NULL COMMENT 'data_id', - `group_id` varchar(128) NOT NULL COMMENT 'group_id', - `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', - `nid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增长标识', - PRIMARY KEY (`nid`), - UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`), - KEY `idx_tenant_id` (`tenant_id`) + `id` bigint(20) NOT NULL COMMENT 'id', + `tag_name` varchar(128) NOT NULL COMMENT 'tag_name', + `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type', + `data_id` varchar(255) NOT NULL COMMENT 'data_id', + `group_id` varchar(128) NOT NULL COMMENT 'group_id', + `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', + `nid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增长标识', + PRIMARY KEY (`nid`), + UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`), + KEY `idx_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation'; /******************************************/ /* 表名称 = group_capacity */ /******************************************/ CREATE TABLE `group_capacity` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群', - `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值', - `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', - `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值', - `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值', - `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值', - `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量', - `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_group_id` (`group_id`) + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群', + `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值', + `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', + `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值', + `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值', + `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值', + `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_group_id` (`group_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表'; /******************************************/ /* 表名称 = his_config_info */ /******************************************/ CREATE TABLE `his_config_info` ( - `id` bigint(20) unsigned NOT NULL COMMENT 'id', - `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增标识', - `data_id` varchar(255) NOT NULL COMMENT 'data_id', - `group_id` varchar(128) NOT NULL COMMENT 'group_id', - `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', - `content` longtext NOT NULL COMMENT 'content', - `md5` varchar(32) DEFAULT NULL COMMENT 'md5', - `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', - `src_user` text COMMENT 'source user', - `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', - `op_type` char(10) DEFAULT NULL COMMENT 'operation type', - `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', - `encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥', - PRIMARY KEY (`nid`), - KEY `idx_gmt_create` (`gmt_create`), - KEY `idx_gmt_modified` (`gmt_modified`), - KEY `idx_did` (`data_id`) + `id` bigint(20) unsigned NOT NULL COMMENT 'id', + `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增标识', + `data_id` varchar(255) NOT NULL COMMENT 'data_id', + `group_id` varchar(128) NOT NULL COMMENT 'group_id', + `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', + `content` longtext NOT NULL COMMENT 'content', + `md5` varchar(32) DEFAULT NULL COMMENT 'md5', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `src_user` text COMMENT 'source user', + `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', + `op_type` char(10) DEFAULT NULL COMMENT 'operation type', + `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段', + `encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥', + `publish_type` varchar(50) DEFAULT 'formal' COMMENT 'publish type gray or formal',, + `ext_info` longtext DEFAULT NULL COMMENT 'ext info', + PRIMARY KEY (`nid`), + KEY `idx_gmt_create` (`gmt_create`), + KEY `idx_gmt_modified` (`gmt_modified`), + KEY `idx_did` (`data_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造'; @@ -160,51 +169,51 @@ CREATE TABLE `his_config_info` ( /* 表名称 = tenant_capacity */ /******************************************/ CREATE TABLE `tenant_capacity` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', - `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID', - `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值', - `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', - `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值', - `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数', - `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值', - `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量', - `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_id` (`tenant_id`) + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID', + `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值', + `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', + `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值', + `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数', + `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值', + `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量', + `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表'; CREATE TABLE `tenant_info` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', - `kp` varchar(128) NOT NULL COMMENT 'kp', - `tenant_id` varchar(128) default '' COMMENT 'tenant_id', - `tenant_name` varchar(128) default '' COMMENT 'tenant_name', - `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc', - `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source', - `gmt_create` bigint(20) NOT NULL COMMENT '创建时间', - `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`), - KEY `idx_tenant_id` (`tenant_id`) + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', + `kp` varchar(128) NOT NULL COMMENT 'kp', + `tenant_id` varchar(128) default '' COMMENT 'tenant_id', + `tenant_name` varchar(128) default '' COMMENT 'tenant_name', + `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc', + `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source', + `gmt_create` bigint(20) NOT NULL COMMENT '创建时间', + `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`), + KEY `idx_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info'; CREATE TABLE `users` ( - `username` varchar(50) NOT NULL PRIMARY KEY COMMENT 'username', - `password` varchar(500) NOT NULL COMMENT 'password', - `enabled` boolean NOT NULL COMMENT 'enabled' + `username` varchar(50) NOT NULL PRIMARY KEY COMMENT 'username', + `password` varchar(500) NOT NULL COMMENT 'password', + `enabled` boolean NOT NULL COMMENT 'enabled' ); CREATE TABLE `roles` ( - `username` varchar(50) NOT NULL COMMENT 'username', - `role` varchar(50) NOT NULL COMMENT 'role', - UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE + `username` varchar(50) NOT NULL COMMENT 'username', + `role` varchar(50) NOT NULL COMMENT 'role', + UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE ); CREATE TABLE `permissions` ( - `role` varchar(50) NOT NULL COMMENT 'role', - `resource` varchar(128) NOT NULL COMMENT 'resource', - `action` varchar(8) NOT NULL COMMENT 'action', - UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE + `role` varchar(50) NOT NULL COMMENT 'role', + `resource` varchar(128) NOT NULL COMMENT 'resource', + `action` varchar(8) NOT NULL COMMENT 'action', + UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE ); diff --git a/persistence/src/test/resources/META-INF/derby-schema.sql b/persistence/src/test/resources/META-INF/derby-schema.sql index 601d38ab2e6..6a2392369ca 100644 --- a/persistence/src/test/resources/META-INF/derby-schema.sql +++ b/persistence/src/test/resources/META-INF/derby-schema.sql @@ -1,4 +1,4 @@ -build/* +/* * Copyright 1999-2018 Alibaba Group Holding Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,46 +17,48 @@ build/* CREATE SCHEMA nacos AUTHORIZATION nacos; CREATE TABLE config_info ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128) DEFAULT NULL, - src_ip varchar(50) DEFAULT NULL, - c_desc varchar(256) DEFAULT NULL, - c_use varchar(64) DEFAULT NULL, - effect varchar(64) DEFAULT NULL, - type varchar(64) DEFAULT NULL, - c_schema LONG VARCHAR DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint configinfo_id_key PRIMARY KEY (id), - constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128) DEFAULT NULL, + src_ip varchar(50) DEFAULT NULL, + c_desc varchar(256) DEFAULT NULL, + c_use varchar(64) DEFAULT NULL, + effect varchar(64) DEFAULT NULL, + type varchar(64) DEFAULT NULL, + c_schema LONG VARCHAR DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfo_id_key PRIMARY KEY (id), + constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); CREATE INDEX configinfo_dataid_key_idx ON config_info(data_id); CREATE INDEX configinfo_groupid_key_idx ON config_info(group_id); CREATE INDEX configinfo_dataid_group_key_idx ON config_info(data_id, group_id); CREATE TABLE his_config_info ( - id bigint NOT NULL, - nid bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - op_type char(10) DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); + id bigint NOT NULL, + nid bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + publish_type varchar(50) DEFAULT 'formal', + ext_info CLOB, + op_type char(10) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); CREATE INDEX hisconfiginfo_dataid_key_idx ON his_config_info(data_id); CREATE INDEX hisconfiginfo_gmt_create_idx ON his_config_info(gmt_create); @@ -64,164 +66,174 @@ CREATE INDEX hisconfiginfo_gmt_modified_idx ON his_config_info(gmt_modified); CREATE TABLE config_info_beta ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - beta_ips varchar(1024), - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint configinfobeta_id_key PRIMARY KEY (id), - constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + beta_ips varchar(1024), + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfobeta_id_key PRIMARY KEY (id), + constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); CREATE TABLE config_info_tag ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - tag_id varchar(128) NOT NULL, - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - constraint configinfotag_id_key PRIMARY KEY (id), - constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); - -CREATE TABLE config_info_aggr ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - datum_id varchar(255) NOT NULL, - app_name varchar(128), - content CLOB, - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - constraint configinfoaggr_id_key PRIMARY KEY (id), - constraint uk_configinfoaggr_datagrouptenantdatum UNIQUE (data_id,group_id,tenant_id,datum_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + tag_id varchar(128) NOT NULL, + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + constraint configinfotag_id_key PRIMARY KEY (id), + constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); + +CREATE TABLE config_info_gray ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + gray_name varchar(128) NOT NULL, + gray_rule CLOB, + app_name varchar(128), + src_ip varchar(128), + src_user varchar(128) default '', + content CLOB, + md5 varchar(32) DEFAULT NULL, + encrypted_data_key varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + constraint configinfogray_id_key PRIMARY KEY (id), + constraint uk_configinfogray_datagrouptenantgrayname UNIQUE (data_id,group_id,tenant_id,gray_name)); +CREATE INDEX config_info_gray_dataid_gmt_modified ON config_info_gray(data_id,gmt_modified); +CREATE INDEX config_info_gray_gmt_modified ON config_info_gray(gmt_modified); CREATE TABLE app_list ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - is_dynamic_collect_disabled smallint DEFAULT 0, - last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', - sub_info_lock_owner varchar(128), - sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', - constraint applist_id_key PRIMARY KEY (id), - constraint uk_appname UNIQUE (app_name)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + is_dynamic_collect_disabled smallint DEFAULT 0, + last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', + sub_info_lock_owner varchar(128), + sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', + constraint applist_id_key PRIMARY KEY (id), + constraint uk_appname UNIQUE (app_name)); CREATE TABLE app_configdata_relation_subs ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint configdatarelationsubs_id_key PRIMARY KEY (id), - constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationsubs_id_key PRIMARY KEY (id), + constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); CREATE TABLE app_configdata_relation_pubs ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint configdatarelationpubs_id_key PRIMARY KEY (id), - constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationpubs_id_key PRIMARY KEY (id), + constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); CREATE TABLE config_tags_relation ( - id bigint NOT NULL, - tag_name varchar(128) NOT NULL, - tag_type varchar(64) DEFAULT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) DEFAULT '', - nid bigint NOT NULL generated by default as identity, - constraint config_tags_id_key PRIMARY KEY (nid), - constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); + id bigint NOT NULL, + tag_name varchar(128) NOT NULL, + tag_type varchar(64) DEFAULT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + nid bigint NOT NULL generated by default as identity, + constraint config_tags_id_key PRIMARY KEY (nid), + constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); CREATE INDEX config_tags_tenant_id_idx ON config_tags_relation(tenant_id); CREATE TABLE group_capacity ( - id bigint NOT NULL generated by default as identity, - group_id varchar(128) DEFAULT '', - quota int DEFAULT 0, - usage int DEFAULT 0, - max_size int DEFAULT 0, - max_aggr_count int DEFAULT 0, - max_aggr_size int DEFAULT 0, - max_history_count int DEFAULT 0, - gmt_create timestamp DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint group_capacity_id_key PRIMARY KEY (id), - constraint uk_group_id UNIQUE (group_id)); + id bigint NOT NULL generated by default as identity, + group_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint group_capacity_id_key PRIMARY KEY (id), + constraint uk_group_id UNIQUE (group_id)); CREATE TABLE tenant_capacity ( - id bigint NOT NULL generated by default as identity, - tenant_id varchar(128) DEFAULT '', - quota int DEFAULT 0, - usage int DEFAULT 0, - max_size int DEFAULT 0, - max_aggr_count int DEFAULT 0, - max_aggr_size int DEFAULT 0, - max_history_count int DEFAULT 0, - gmt_create timestamp DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint tenant_capacity_id_key PRIMARY KEY (id), - constraint uk_tenant_id UNIQUE (tenant_id)); + id bigint NOT NULL generated by default as identity, + tenant_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint tenant_capacity_id_key PRIMARY KEY (id), + constraint uk_tenant_id UNIQUE (tenant_id)); CREATE TABLE tenant_info ( - id bigint NOT NULL generated by default as identity, - kp varchar(128) NOT NULL, - tenant_id varchar(128) DEFAULT '', - tenant_name varchar(128) DEFAULT '', - tenant_desc varchar(256) DEFAULT NULL, - create_source varchar(32) DEFAULT NULL, - gmt_create bigint NOT NULL, - gmt_modified bigint NOT NULL, - constraint tenant_info_id_key PRIMARY KEY (id), - constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); + id bigint NOT NULL generated by default as identity, + kp varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + tenant_name varchar(128) DEFAULT '', + tenant_desc varchar(256) DEFAULT NULL, + create_source varchar(32) DEFAULT NULL, + gmt_create bigint NOT NULL, + gmt_modified bigint NOT NULL, + constraint tenant_info_id_key PRIMARY KEY (id), + constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id); CREATE TABLE users ( - username varchar(50) NOT NULL PRIMARY KEY, - password varchar(500) NOT NULL, - enabled boolean NOT NULL DEFAULT true + username varchar(50) NOT NULL PRIMARY KEY, + password varchar(500) NOT NULL, + enabled boolean NOT NULL DEFAULT true ); CREATE TABLE roles ( - username varchar(50) NOT NULL, - role varchar(50) NOT NULL, - constraint uk_username_role UNIQUE (username,role) + username varchar(50) NOT NULL, + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) ); CREATE TABLE permissions ( - role varchar(50) NOT NULL, - resource varchar(512) NOT NULL, - action varchar(8) NOT NULL, - constraint uk_role_permission UNIQUE (role,resource,action) + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) ); + /******************************************/ /* ipv6 support */ /******************************************/ -ALTER TABLE `config_info_tag` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `his_config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL AFTER `src_user`; +ALTER TABLE config_info_tag ADD src_ip varchar(50) DEFAULT NULL; + +ALTER TABLE his_config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info_beta ADD src_ip varchar(50) DEFAULT NULL ; -ALTER TABLE `config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `config_info_beta` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; \ No newline at end of file +ALTER TABLE his_config_info ADD publish_type varchar(50) DEFAULT 'formal'; +ALTER TABLE his_config_info ADD ext_info CLOB DEFAULT NULL ; diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/FieldConstant.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/FieldConstant.java index d5c7576e90c..7dff3669904 100644 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/FieldConstant.java +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/FieldConstant.java @@ -80,6 +80,12 @@ public class FieldConstant { public static final String TAG_ID = "tagId"; + public static final String PUBLISH_TYPE = "publishType"; + + public static final String GRAY_NAME = "grayName"; + + public static final String GRAY_RULE = "grayRule"; + public static final String QUOTA = "quota"; public static final String MAX_SIZE = "maxSize"; diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/TableConstant.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/TableConstant.java index 8ff06df344d..934bc4ee128 100644 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/TableConstant.java +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/constants/TableConstant.java @@ -26,12 +26,12 @@ public class TableConstant { public static final String CONFIG_INFO = "config_info"; - public static final String CONFIG_INFO_AGGR = "config_info_aggr"; - public static final String CONFIG_INFO_BETA = "config_info_beta"; public static final String CONFIG_INFO_TAG = "config_info_tag"; + public static final String CONFIG_INFO_GRAY = "config_info_gray"; + public static final String CONFIG_TAGS_RELATION = "config_tags_relation"; public static final String GROUP_CAPACITY = "group_capacity"; diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoAggrMapperByDerby.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoAggrMapperByDerby.java deleted file mode 100644 index 3750ab86512..00000000000 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoAggrMapperByDerby.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.plugin.datasource.impl.derby; - -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoAggrMapper; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; - -import java.util.List; - -/** - * The derby implementation of ConfigInfoAggrMapper. - * - * @author hyx - **/ -public class ConfigInfoAggrMapperByDerby extends AbstractMapperByDerby implements ConfigInfoAggrMapper { - - @Override - public MapperResult findConfigInfoAggrByPageFetchRows(MapperContext context) { - final Integer startRow = context.getStartRow(); - final Integer pageSize = context.getPageSize(); - final String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID); - final String groupId = (String) context.getWhereParameter(FieldConstant.GROUP_ID); - final String tenantId = (String) context.getWhereParameter(FieldConstant.TENANT_ID); - - String sql = - "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE data_id=? AND " - + "group_id=? AND tenant_id=? ORDER BY datum_id OFFSET " + startRow + " ROWS FETCH NEXT " - + pageSize + " ROWS ONLY"; - List paramList = CollectionUtils.list(dataId, groupId, tenantId); - return new MapperResult(sql, paramList); - } - - @Override - public String getDataSource() { - return DataSourceConstant.DERBY; - } -} diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoGrayMapperByDerby.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoGrayMapperByDerby.java new file mode 100644 index 00000000000..bb9f4c01e09 --- /dev/null +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoGrayMapperByDerby.java @@ -0,0 +1,59 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.datasource.impl.derby; + +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; +import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; +import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper; +import com.alibaba.nacos.plugin.datasource.model.MapperContext; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; + +import java.util.Collections; + +/** + * The derby implementation of ConfigInfoGrayMapper. + * + * @author rong + **/ + +public class ConfigInfoGrayMapperByDerby extends AbstractMapperByDerby implements ConfigInfoGrayMapper { + + @Override + public MapperResult findAllConfigInfoGrayForDumpAllFetchRows(MapperContext context) { + String sql = "SELECT t.id,data_id,group_id,tenant_id,gray_name,gray_rule,app_name,content,md5,gmt_modified " + + " FROM ( SELECT id FROM config_info_gray ORDER BY id OFFSET " + context.getStartRow() + + " ROWS FETCH NEXT " + context.getPageSize() + " ROWS ONLY ) " + + " g, config_info_gray t WHERE g.id = t.id"; + return new MapperResult(sql, Collections.emptyList()); + } + + @Override + public MapperResult findChangeConfig(MapperContext context) { + String sql = "SELECT id, data_id, group_id, tenant_id, app_name, content,gray_name,gray_rule, " + + "gmt_modified, encrypted_data_key FROM config_info_gray WHERE " + + "gmt_modified >= ? and id > ? order by id OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY"; + return new MapperResult(sql, CollectionUtils.list(context.getWhereParameter(FieldConstant.START_TIME), + context.getWhereParameter(FieldConstant.LAST_MAX_ID), + context.getWhereParameter(FieldConstant.PAGE_SIZE))); + } + + @Override + public String getDataSource() { + return DataSourceConstant.DERBY; + } +} diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerby.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerby.java index 041d580ff7e..739c3712f6e 100644 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerby.java +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerby.java @@ -42,7 +42,8 @@ public MapperResult removeConfigHistory(MapperContext context) { @Override public MapperResult pageFindConfigHistoryFetchRows(MapperContext context) { String sql = - "SELECT nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,gmt_create,gmt_modified FROM his_config_info " + "SELECT nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,ext_info,publish_type,gmt_create,gmt_modified " + + "FROM his_config_info " + "WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY nid DESC OFFSET " + context.getStartRow() + " ROWS FETCH NEXT " + context.getPageSize() + " ROWS ONLY"; return new MapperResult(sql, CollectionUtils.list(context.getWhereParameter(FieldConstant.DATA_ID), @@ -57,9 +58,11 @@ public String getDataSource() { @Override public MapperResult findDeletedConfig(MapperContext context) { return new MapperResult( - "SELECT data_id, group_id, tenant_id,gmt_modified,nid FROM his_config_info WHERE op_type = 'D' AND " - + "gmt_modified >= ? and nid > ? order by nid OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY", - CollectionUtils.list(context.getWhereParameter(FieldConstant.START_TIME), + "SELECT id, nid, data_id, group_id, app_name, content, md5, gmt_create, gmt_modified, src_user, src_ip, op_type, tenant_id, " + + "publish_type, ext_info, encrypted_data_key FROM his_config_info WHERE op_type = 'D' AND " + + "publish_type = ? and gmt_modified >= ? and nid > ? order by nid OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY", + CollectionUtils.list(context.getWhereParameter(FieldConstant.PUBLISH_TYPE), + context.getWhereParameter(FieldConstant.START_TIME), context.getWhereParameter(FieldConstant.LAST_MAX_ID), context.getWhereParameter(FieldConstant.PAGE_SIZE))); } diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoAggrMapperByMySql.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoAggrMapperByMySql.java deleted file mode 100644 index 03382271cb0..00000000000 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoAggrMapperByMySql.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.plugin.datasource.impl.mysql; - -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoAggrMapper; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; - -import java.util.List; - -/** - * The mysql implementation of ConfigInfoAggrMapper. - * - * @author hyx - **/ -public class ConfigInfoAggrMapperByMySql extends AbstractMapperByMysql implements ConfigInfoAggrMapper { - - @Override - public MapperResult findConfigInfoAggrByPageFetchRows(MapperContext context) { - int startRow = context.getStartRow(); - int pageSize = context.getPageSize(); - String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID); - String groupId = (String) context.getWhereParameter(FieldConstant.GROUP_ID); - String tenantId = (String) context.getWhereParameter(FieldConstant.TENANT_ID); - - String sql = - "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE data_id= ? AND " - + "group_id= ? AND tenant_id= ? ORDER BY datum_id LIMIT " + startRow + "," + pageSize; - List paramList = CollectionUtils.list(dataId, groupId, tenantId); - return new MapperResult(sql, paramList); - } - - @Override - public String getDataSource() { - return DataSourceConstant.MYSQL; - } -} diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoGrayMapperByMySql.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoGrayMapperByMySql.java new file mode 100644 index 00000000000..f471da23a40 --- /dev/null +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoGrayMapperByMySql.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.datasource.impl.mysql; + +import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; +import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper; +import com.alibaba.nacos.plugin.datasource.model.MapperContext; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; + +import java.util.Collections; + +/** + * The mysql implementation of ConfigInfoGrayMapper. + * + * @author rong + **/ + +public class ConfigInfoGrayMapperByMySql extends AbstractMapperByMysql implements ConfigInfoGrayMapper { + + @Override + public MapperResult findAllConfigInfoGrayForDumpAllFetchRows(MapperContext context) { + String sql = " SELECT t.id,data_id,group_id,tenant_id,gray_name,gray_rule,app_name,content,md5,gmt_modified " + + " FROM ( SELECT id FROM config_info_gray ORDER BY id LIMIT " + context.getStartRow() + "," + + context.getPageSize() + " ) " + "g, config_info_gray t WHERE g.id = t.id "; + return new MapperResult(sql, Collections.emptyList()); + } + + @Override + public String getDataSource() { + return DataSourceConstant.MYSQL; + } +} diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySql.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySql.java index 39ec2a8ca0e..ee7700e9229 100644 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySql.java +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySql.java @@ -41,8 +41,8 @@ public MapperResult removeConfigHistory(MapperContext context) { @Override public MapperResult pageFindConfigHistoryFetchRows(MapperContext context) { String sql = - "SELECT nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,gmt_create,gmt_modified FROM his_config_info " - + "WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY nid DESC LIMIT " + "SELECT nid,data_id,group_id,tenant_id,app_name,src_ip,src_user,op_type,ext_info,publish_type,gmt_create,gmt_modified " + + "FROM his_config_info " + "WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY nid DESC LIMIT " + context.getStartRow() + "," + context.getPageSize(); return new MapperResult(sql, CollectionUtils.list(context.getWhereParameter(FieldConstant.DATA_ID), context.getWhereParameter(FieldConstant.GROUP_ID), context.getWhereParameter(FieldConstant.TENANT_ID))); diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/ConfigInfoAggrMapper.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/ConfigInfoAggrMapper.java deleted file mode 100644 index 0b3bae1fa0e..00000000000 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/ConfigInfoAggrMapper.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.plugin.datasource.mapper; - -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.constants.TableConstant; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; - -import java.util.ArrayList; -import java.util.List; - -/** - * The mapper of config info. - * - * @author hyx - **/ - -public interface ConfigInfoAggrMapper extends Mapper { - - /** - * To delete aggregated data in bulk, you need to specify a size of datum list. - * The default sql: - * DELETE FROM config_info_aggr WHERE data_id=? AND group_id=? AND tenant_id=? AND datum_id IN (...) - * - * @param context The context of datum_id, data_id, group_id, tenant_id - * @return The sql of deleting aggregated data in bulk. - */ - default MapperResult batchRemoveAggr(MapperContext context) { - final List datumList = (List) context.getWhereParameter(FieldConstant.DATUM_ID); - final String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID); - final String group = (String) context.getWhereParameter(FieldConstant.GROUP_ID); - final String tenantTmp = (String) context.getWhereParameter(FieldConstant.TENANT_ID); - - List paramList = new ArrayList<>(); - paramList.add(dataId); - paramList.add(group); - paramList.add(tenantTmp); - - final StringBuilder placeholderString = new StringBuilder(); - for (int i = 0; i < datumList.size(); i++) { - if (i != 0) { - placeholderString.append(", "); - } - placeholderString.append('?'); - paramList.add(datumList.get(i)); - } - - String sql = - "DELETE FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? AND datum_id IN (" - + placeholderString + ")"; - - return new MapperResult(sql, paramList); - } - - /** - * Get count of aggregation config info. - * The default sql: - * SELECT count(*) FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? - * - * @param context The context of datum_id, isIn, data_id, group_id, tenant_id - * @return The sql of getting count of aggregation config info. - */ - default MapperResult aggrConfigInfoCount(MapperContext context) { - final List datumIds = (List) context.getWhereParameter(FieldConstant.DATUM_ID); - final Boolean isIn = (Boolean) context.getWhereParameter(FieldConstant.IS_IN); - String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID); - String group = (String) context.getWhereParameter(FieldConstant.GROUP_ID); - String tenantTmp = (String) context.getWhereParameter(FieldConstant.TENANT_ID); - - List paramList = CollectionUtils.list(dataId, group, tenantTmp); - - StringBuilder sql = new StringBuilder( - "SELECT count(*) FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? AND datum_id"); - if (isIn) { - sql.append(" IN ("); - } else { - sql.append(" NOT IN ("); - } - for (int i = 0; i < datumIds.size(); i++) { - if (i > 0) { - sql.append(", "); - } - sql.append('?'); - paramList.add(datumIds.get(i)); - } - sql.append(')'); - - return new MapperResult(sql.toString(), paramList); - } - - /** - * Find all data before aggregation under a dataId. It is guaranteed not to return NULL. - * The default sql: - * SELECT data_id,group_id,tenant_id,datum_id,app_name,content - * FROM config_info_aggr WHERE data_id=? AND group_id=? AND tenant_id=? ORDER BY datum_id - * - * @param context The context of data_id, group_id, tenant_id - * @return The sql of finding all data before aggregation under a dataId. - */ - default MapperResult findConfigInfoAggrIsOrdered(MapperContext context) { - String dataId = (String) context.getWhereParameter(FieldConstant.DATA_ID); - String groupId = (String) context.getWhereParameter(FieldConstant.GROUP_ID); - String tenantId = (String) context.getWhereParameter(FieldConstant.TENANT_ID); - - String sql = "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM " - + "config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY datum_id"; - List paramList = CollectionUtils.list(dataId, groupId, tenantId); - - return new MapperResult(sql, paramList); - } - - /** - * Query aggregation config info. - * The default sql: - * SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE data_id=? AND - * group_id=? AND tenant_id=? ORDER BY datum_id LIMIT startRow,pageSize - * - * @param context The context of startRow, pageSize, data_id, group_id, tenant_id - * @return The sql of querying aggregation config info. - */ - MapperResult findConfigInfoAggrByPageFetchRows(MapperContext context); - - /** - * Find all aggregated data sets. - * The default sql: - * SELECT DISTINCT data_id, group_id, tenant_id FROM config_info_aggr - * - * @param context sql paramMap - * @return The sql of finding all aggregated data sets. - */ - default MapperResult findAllAggrGroupByDistinct(MapperContext context) { - return new MapperResult("SELECT DISTINCT data_id, group_id, tenant_id FROM config_info_aggr", - CollectionUtils.list()); - } - - /** - * 获取返回表名. - * - * @return 表名 - */ - default String getTableName() { - return TableConstant.CONFIG_INFO_AGGR; - } -} diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/ConfigInfoGrayMapper.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/ConfigInfoGrayMapper.java new file mode 100644 index 00000000000..de2bf9dd1d0 --- /dev/null +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/ConfigInfoGrayMapper.java @@ -0,0 +1,97 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.nacos.plugin.datasource.mapper; + +import com.alibaba.nacos.common.utils.CollectionUtils; +import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; +import com.alibaba.nacos.plugin.datasource.constants.TableConstant; +import com.alibaba.nacos.plugin.datasource.model.MapperContext; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; + +/** + * The config gray info mapper. + * + * @author rong + **/ + +public interface ConfigInfoGrayMapper extends Mapper { + + /** + * Update gray configuration information. The default sql: UPDATE config_info_gray SET content=?, md5 = ?, + * src_ip=?,src_user=?,gmt_modified=?,app_name=?,gray_rule=? WHERE data_id=? AND group_id=? AND tenant_id=? AND + * gray_name=? AND (md5=? or md5 is null or md5='') + * + * @param context sql paramMap + * @return The sql of updating gray configuration information. + */ + default MapperResult updateConfigInfo4GrayCas(MapperContext context) { + Object content = context.getUpdateParameter(FieldConstant.CONTENT); + Object md5 = context.getUpdateParameter(FieldConstant.MD5); + Object srcIp = context.getUpdateParameter(FieldConstant.SRC_IP); + Object srcUser = context.getUpdateParameter(FieldConstant.SRC_USER); + Object gmtModified = context.getUpdateParameter(FieldConstant.GMT_MODIFIED); + Object appName = context.getUpdateParameter(FieldConstant.APP_NAME); + + Object dataId = context.getWhereParameter(FieldConstant.DATA_ID); + Object groupId = context.getWhereParameter(FieldConstant.GROUP_ID); + Object tenantId = context.getWhereParameter(FieldConstant.TENANT_ID); + Object grayName = context.getWhereParameter(FieldConstant.GRAY_NAME); + Object grayRule = context.getWhereParameter(FieldConstant.GRAY_RULE); + Object oldMd5 = context.getWhereParameter(FieldConstant.MD5); + String sql = "UPDATE config_info_gray SET content = ?, md5 = ?, src_ip = ?,src_user = ?,gmt_modified = " + + getFunction("NOW()") + ",app_name = ?, gray_rule = ?" + + "WHERE data_id = ? AND group_id = ? AND tenant_id = ? AND gray_name = ? AND (md5 = ? OR md5 IS NULL OR md5 = '')"; + return new MapperResult(sql, + CollectionUtils.list(content, md5, srcIp, srcUser, appName, grayRule, dataId, groupId, + tenantId, grayName, oldMd5)); + } + + /** + * Query change config.
The default sql: SELECT data_id, group_id, tenant_id, app_name, content, + * gmt_modified,encrypted_data_key FROM config_info WHERE gmt_modified >=? AND gmt_modified <= ? + * + * @param context sql paramMap + * @return The sql of querying change config. + */ + default MapperResult findChangeConfig(MapperContext context) { + String sql = + "SELECT id, data_id, group_id, tenant_id, app_name,content,gray_name,gray_rule,md5, gmt_modified, encrypted_data_key " + + "FROM config_info_gray WHERE " + "gmt_modified >= ? and id > ? order by id limit ? "; + return new MapperResult(sql, CollectionUtils.list(context.getWhereParameter(FieldConstant.START_TIME), + context.getWhereParameter(FieldConstant.LAST_MAX_ID), + context.getWhereParameter(FieldConstant.PAGE_SIZE))); + } + + /** + * Query all gray config info for dump task. The default sql: SELECT + * t.id,data_id,group_id,tenant_id,gray_name,app_name,content,md5,gmt_modified FROM ( SELECT id FROM + * config_info_gray ORDER BY id LIMIT startRow,pageSize ) g, config_info_gray t WHERE g.id = t.id + * + * @param context The start index. + * @return The sql of querying all gray config info for dump task. + */ + MapperResult findAllConfigInfoGrayForDumpAllFetchRows(MapperContext context); + + /** + * 获取返回表名. + * + * @return 表名 + */ + default String getTableName() { + return TableConstant.CONFIG_INFO_GRAY; + } +} diff --git a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/HistoryConfigInfoMapper.java b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/HistoryConfigInfoMapper.java index de6a2f60953..cf7a4e74c08 100644 --- a/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/HistoryConfigInfoMapper.java +++ b/plugin/datasource/src/main/java/com/alibaba/nacos/plugin/datasource/mapper/HistoryConfigInfoMapper.java @@ -61,9 +61,11 @@ default MapperResult findConfigHistoryCountByTime(MapperContext context) { */ default MapperResult findDeletedConfig(MapperContext context) { return new MapperResult( - "SELECT data_id, group_id, tenant_id,gmt_modified,nid FROM his_config_info WHERE op_type = 'D' AND " - + "gmt_modified >= ? and nid > ? order by nid limit ? ", - CollectionUtils.list(context.getWhereParameter(FieldConstant.START_TIME), + "SELECT id, nid, data_id, group_id, app_name, content, md5, gmt_create, gmt_modified, src_user, src_ip, op_type, tenant_id, " + + "publish_type, ext_info, encrypted_data_key FROM his_config_info WHERE op_type = 'D' AND " + + "publish_type = ? and gmt_modified >= ? and nid > ? order by nid limit ? ", + CollectionUtils.list(context.getWhereParameter(FieldConstant.PUBLISH_TYPE), + context.getWhereParameter(FieldConstant.START_TIME), context.getWhereParameter(FieldConstant.LAST_MAX_ID), context.getWhereParameter(FieldConstant.PAGE_SIZE))); } diff --git a/plugin/datasource/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.datasource.mapper.Mapper b/plugin/datasource/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.datasource.mapper.Mapper index f0d6adeb57f..0a7fa58522f 100644 --- a/plugin/datasource/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.datasource.mapper.Mapper +++ b/plugin/datasource/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.datasource.mapper.Mapper @@ -14,20 +14,20 @@ # limitations under the License. # -com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoAggrMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoBetaMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoTagMapperByMySql +com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoGrayMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigTagsRelationMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.HistoryConfigInfoMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.TenantInfoMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.TenantCapacityMapperByMySql com.alibaba.nacos.plugin.datasource.impl.mysql.GroupCapacityMapperByMysql -com.alibaba.nacos.plugin.datasource.impl.derby.ConfigInfoAggrMapperByDerby com.alibaba.nacos.plugin.datasource.impl.derby.ConfigInfoBetaMapperByDerby com.alibaba.nacos.plugin.datasource.impl.derby.ConfigInfoMapperByDerby com.alibaba.nacos.plugin.datasource.impl.derby.ConfigInfoTagMapperByDerby +com.alibaba.nacos.plugin.datasource.impl.derby.ConfigInfoGrayMapperByDerby com.alibaba.nacos.plugin.datasource.impl.derby.ConfigInfoTagsRelationMapperByDerby com.alibaba.nacos.plugin.datasource.impl.derby.HistoryConfigInfoMapperByDerby com.alibaba.nacos.plugin.datasource.impl.derby.TenantInfoMapperByDerby diff --git a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/MapperManagerTest.java b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/MapperManagerTest.java index eff15277ce5..ab8bc7b764c 100644 --- a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/MapperManagerTest.java +++ b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/MapperManagerTest.java @@ -18,7 +18,7 @@ import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; import com.alibaba.nacos.plugin.datasource.impl.mysql.AbstractMapperByMysql; -import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoAggrMapper; +import com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper; import com.alibaba.nacos.plugin.datasource.mapper.Mapper; import com.alibaba.nacos.plugin.datasource.mapper.TestMapper; import org.junit.jupiter.api.Test; @@ -55,7 +55,7 @@ void testJoin() { public String getTableName() { return "test"; } - + @Override public String getDataSource() { return DataSourceConstant.MYSQL; @@ -78,7 +78,7 @@ void testFindMapper() { void testEnableDataSourceLogJoin() { MapperManager.join(new TestMapper()); MapperManager instance = MapperManager.instance(true); - ConfigInfoAggrMapper mapper = instance.findMapper(DataSourceConstant.MYSQL, "enable_data_source_log_test"); + ConfigInfoGrayMapper mapper = instance.findMapper(DataSourceConstant.MYSQL, "enable_data_source_log_test"); assertNotNull(mapper); } diff --git a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoAggrMapperByDerbyTest.java b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoAggrMapperByDerbyTest.java deleted file mode 100644 index e0abf043c1e..00000000000 --- a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/ConfigInfoAggrMapperByDerbyTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.plugin.datasource.impl.derby; - -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.constants.TableConstant; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class ConfigInfoAggrMapperByDerbyTest { - - private ConfigInfoAggrMapperByDerby configInfoAggrMapperByDerby; - - @BeforeEach - void setUp() throws Exception { - this.configInfoAggrMapperByDerby = new ConfigInfoAggrMapperByDerby(); - } - - @Test - void testBatchRemoveAggr() { - List datumList = Arrays.asList("1", "2", "3", "4", "5"); - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - List argList = CollectionUtils.list(dataId, groupId, tenantId); - argList.addAll(datumList); - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATUM_ID, datumList); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - - MapperResult result = configInfoAggrMapperByDerby.batchRemoveAggr(context); - String sql = result.getSql(); - List paramList = result.getParamList(); - - assertEquals(sql, - "DELETE FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? " + "AND datum_id IN (?, ?, ?, ?, ?)"); - assertEquals(paramList, argList); - } - - @Test - void testAggrConfigInfoCount() { - List datumIds = Arrays.asList("1", "2", "3", "4", "5"); - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - List argList = CollectionUtils.list(dataId, groupId, tenantId); - argList.addAll(datumIds); - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATUM_ID, datumIds); - context.putWhereParameter(FieldConstant.IS_IN, true); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - - MapperResult mapperResult = configInfoAggrMapperByDerby.aggrConfigInfoCount(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - - assertEquals(sql, "SELECT count(*) FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? " - + "AND datum_id IN (?, ?, ?, ?, ?)"); - assertEquals(paramList, argList); - } - - @Test - void testFindConfigInfoAggrIsOrdered() { - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - - MapperResult mapperResult = configInfoAggrMapperByDerby.findConfigInfoAggrIsOrdered(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - - assertEquals(sql, "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM " - + "config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY datum_id"); - assertEquals(paramList, CollectionUtils.list(dataId, groupId, tenantId)); - } - - @Test - void testFindConfigInfoAggrByPageFetchRows() { - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - Integer startRow = 0; - Integer pageSize = 5; - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - context.setStartRow(startRow); - context.setPageSize(pageSize); - - MapperResult mapperResult = configInfoAggrMapperByDerby.findConfigInfoAggrByPageFetchRows(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - assertEquals(sql, "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE " - + "data_id=? AND group_id=? AND tenant_id=? ORDER BY datum_id OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY"); - assertEquals(paramList, CollectionUtils.list(dataId, groupId, tenantId)); - } - - @Test - void testFindAllAggrGroupByDistinct() { - MapperResult sql = configInfoAggrMapperByDerby.findAllAggrGroupByDistinct(null); - assertEquals("SELECT DISTINCT data_id, group_id, tenant_id FROM config_info_aggr", sql.getSql()); - } - - @Test - void testGetTableName() { - String tableName = configInfoAggrMapperByDerby.getTableName(); - assertEquals(TableConstant.CONFIG_INFO_AGGR, tableName); - } - - @Test - void testGetDataSource() { - String dataSource = configInfoAggrMapperByDerby.getDataSource(); - assertEquals(DataSourceConstant.DERBY, dataSource); - } -} diff --git a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerbyTest.java b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerbyTest.java index 61d16757141..dab7cdc45a7 100644 --- a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerbyTest.java +++ b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/derby/HistoryConfigInfoMapperByDerbyTest.java @@ -43,6 +43,8 @@ class HistoryConfigInfoMapperByDerbyTest { Timestamp endTime = new Timestamp(System.currentTimeMillis()); + String publishType = "formal"; + MapperContext context; private HistoryConfigInfoMapperByDerby historyConfigInfoMapperByDerby; @@ -56,6 +58,7 @@ void setUp() throws Exception { context.putWhereParameter(FieldConstant.LIMIT_SIZE, limitSize); context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId); context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize); + context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType); } @@ -78,10 +81,10 @@ void testFindConfigHistoryCountByTime() { @Test void testFindDeletedConfig() { MapperResult mapperResult = historyConfigInfoMapperByDerby.findDeletedConfig(context); - assertEquals(mapperResult.getSql(), "SELECT data_id, group_id, tenant_id,gmt_modified,nid FROM his_config_info WHERE op_type = 'D' " - + "AND gmt_modified >= ? and nid > ? order by nid OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY"); - - assertArrayEquals(new Object[] {startTime, lastMaxId, pageSize}, mapperResult.getParamList().toArray()); + assertEquals(mapperResult.getSql(), "SELECT id, nid, data_id, group_id, app_name, content, md5, gmt_create, gmt_modified, src_user, src_ip," + + " op_type, tenant_id, publish_type, ext_info, encrypted_data_key FROM his_config_info WHERE op_type = 'D' AND " + + "publish_type = ? and gmt_modified >= ? and nid > ? order by nid OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY"); + assertArrayEquals(new Object[] {publishType, startTime, lastMaxId, pageSize}, mapperResult.getParamList().toArray()); } @Test diff --git a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoAggrMapperByMySqlTest.java b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoAggrMapperByMySqlTest.java deleted file mode 100644 index a55d20fd88b..00000000000 --- a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/ConfigInfoAggrMapperByMySqlTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.nacos.plugin.datasource.impl.mysql; - -import com.alibaba.nacos.common.utils.CollectionUtils; -import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; -import com.alibaba.nacos.plugin.datasource.constants.FieldConstant; -import com.alibaba.nacos.plugin.datasource.constants.TableConstant; -import com.alibaba.nacos.plugin.datasource.model.MapperContext; -import com.alibaba.nacos.plugin.datasource.model.MapperResult; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class ConfigInfoAggrMapperByMySqlTest { - - private ConfigInfoAggrMapperByMySql configInfoAggrMapperByMySql; - - @BeforeEach - void setUp() throws Exception { - configInfoAggrMapperByMySql = new ConfigInfoAggrMapperByMySql(); - } - - @Test - void testBatchRemoveAggr() { - List datumList = Arrays.asList("1", "2", "3", "4", "5"); - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - - List argList = CollectionUtils.list(dataId, groupId, tenantId); - argList.addAll(datumList); - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATUM_ID, datumList); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - - MapperResult mapperResult = configInfoAggrMapperByMySql.batchRemoveAggr(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - - assertEquals(sql, - "DELETE FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? " + "AND datum_id IN (?, ?, ?, ?, ?)"); - - assertEquals(paramList, argList); - } - - @Test - void testAggrConfigInfoCount() { - List datumIds = Arrays.asList("1", "2", "3", "4", "5"); - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - - List argList = CollectionUtils.list(dataId, groupId, tenantId); - argList.addAll(datumIds); - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATUM_ID, datumIds); - context.putWhereParameter(FieldConstant.IS_IN, true); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - MapperResult mapperResult = configInfoAggrMapperByMySql.aggrConfigInfoCount(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - - assertEquals(sql, "SELECT count(*) FROM config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? " - + "AND datum_id IN (?, ?, ?, ?, ?)"); - assertEquals(paramList, argList); - } - - @Test - void testFindConfigInfoAggrIsOrdered() { - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - - MapperResult mapperResult = configInfoAggrMapperByMySql.findConfigInfoAggrIsOrdered(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - - assertEquals(sql, "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM " - + "config_info_aggr WHERE data_id = ? AND group_id = ? AND tenant_id = ? ORDER BY datum_id"); - assertEquals(paramList, Arrays.asList(dataId, groupId, tenantId)); - } - - @Test - void testFindConfigInfoAggrByPageFetchRows() { - String dataId = "data-id"; - String groupId = "group-id"; - String tenantId = "tenant-id"; - Integer startRow = 0; - Integer pageSize = 5; - - MapperContext context = new MapperContext(); - context.putWhereParameter(FieldConstant.DATA_ID, dataId); - context.putWhereParameter(FieldConstant.GROUP_ID, groupId); - context.putWhereParameter(FieldConstant.TENANT_ID, tenantId); - context.setStartRow(startRow); - context.setPageSize(pageSize); - - MapperResult mapperResult = configInfoAggrMapperByMySql.findConfigInfoAggrByPageFetchRows(context); - String sql = mapperResult.getSql(); - List paramList = mapperResult.getParamList(); - - assertEquals(sql, "SELECT data_id,group_id,tenant_id,datum_id,app_name,content FROM config_info_aggr WHERE " - + "data_id= ? AND group_id= ? AND tenant_id= ? ORDER BY datum_id LIMIT 0,5"); - assertEquals(paramList, Arrays.asList(dataId, groupId, tenantId)); - } - - @Test - void testFindAllAggrGroupByDistinct() { - MapperResult mapperResult = configInfoAggrMapperByMySql.findAllAggrGroupByDistinct(null); - assertEquals("SELECT DISTINCT data_id, group_id, tenant_id FROM config_info_aggr", mapperResult.getSql()); - } - - @Test - void testGetTableName() { - String tableName = configInfoAggrMapperByMySql.getTableName(); - assertEquals(TableConstant.CONFIG_INFO_AGGR, tableName); - } - - @Test - void testGetDataSource() { - String dataSource = configInfoAggrMapperByMySql.getDataSource(); - assertEquals(DataSourceConstant.MYSQL, dataSource); - } -} diff --git a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySqlTest.java b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySqlTest.java index c69efda736f..f416b899732 100644 --- a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySqlTest.java +++ b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/impl/mysql/HistoryConfigInfoMapperByMySqlTest.java @@ -43,6 +43,8 @@ class HistoryConfigInfoMapperByMySqlTest { Timestamp endTime = new Timestamp(System.currentTimeMillis()); + String publishType = "formal"; + MapperContext context; private HistoryConfigInfoMapperByMySql historyConfigInfoMapperByMySql; @@ -56,6 +58,7 @@ void setUp() throws Exception { context.putWhereParameter(FieldConstant.LIMIT_SIZE, limitSize); context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId); context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize); + context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType); } @Test @@ -75,10 +78,11 @@ void testFindConfigHistoryCountByTime() { @Test void testFindDeletedConfig() { MapperResult mapperResult = historyConfigInfoMapperByMySql.findDeletedConfig(context); - assertEquals(mapperResult.getSql(), "SELECT data_id, group_id, tenant_id,gmt_modified,nid FROM his_config_info " - + "WHERE op_type = 'D' AND gmt_modified >= ? and nid > ? order by nid limit ? "); + assertEquals(mapperResult.getSql(), "SELECT id, nid, data_id, group_id, app_name, content, md5, gmt_create, gmt_modified, src_user, src_ip," + + " op_type, tenant_id, publish_type, ext_info, encrypted_data_key FROM his_config_info WHERE op_type = 'D' AND " + + "publish_type = ? and gmt_modified >= ? and nid > ? order by nid limit ? "); - assertArrayEquals(new Object[] {startTime, lastMaxId, pageSize}, mapperResult.getParamList().toArray()); + assertArrayEquals(new Object[] {publishType, startTime, lastMaxId, pageSize}, mapperResult.getParamList().toArray()); } @Test diff --git a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/mapper/TestMapper.java b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/mapper/TestMapper.java index 643d242e4da..2ac49c8cf71 100644 --- a/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/mapper/TestMapper.java +++ b/plugin/datasource/src/test/java/com/alibaba/nacos/plugin/datasource/mapper/TestMapper.java @@ -18,14 +18,14 @@ import com.alibaba.nacos.plugin.datasource.constants.DataSourceConstant; import com.alibaba.nacos.plugin.datasource.impl.TestInterface; -import com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoAggrMapperByMySql; +import com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoGrayMapperByMySql; /** * Implement interfaces other than Mapper. just for test * * @author mikolls **/ -public class TestMapper extends ConfigInfoAggrMapperByMySql implements TestInterface { +public class TestMapper extends ConfigInfoGrayMapperByMySql implements TestInterface { @Override public String getTableName() { diff --git a/pom.xml b/pom.xml index 19c67cfb679..f84fd63b718 100644 --- a/pom.xml +++ b/pom.xml @@ -154,7 +154,7 @@ 5.3.39 - 5.7.12 + 5.8.15 9.0.93 diff --git a/test/config-test/src/test/resources/derby-schema.sql b/test/config-test/src/test/resources/derby-schema.sql index f4e93a3aab6..6a2392369ca 100644 --- a/test/config-test/src/test/resources/derby-schema.sql +++ b/test/config-test/src/test/resources/derby-schema.sql @@ -17,46 +17,48 @@ CREATE SCHEMA nacos AUTHORIZATION nacos; CREATE TABLE config_info ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128) DEFAULT NULL, - src_ip varchar(50) DEFAULT NULL, - c_desc varchar(256) DEFAULT NULL, - c_use varchar(64) DEFAULT NULL, - effect varchar(64) DEFAULT NULL, - type varchar(64) DEFAULT NULL, - c_schema LONG VARCHAR DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint configinfo_id_key PRIMARY KEY (id), - constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128) DEFAULT NULL, + src_ip varchar(50) DEFAULT NULL, + c_desc varchar(256) DEFAULT NULL, + c_use varchar(64) DEFAULT NULL, + effect varchar(64) DEFAULT NULL, + type varchar(64) DEFAULT NULL, + c_schema LONG VARCHAR DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfo_id_key PRIMARY KEY (id), + constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); CREATE INDEX configinfo_dataid_key_idx ON config_info(data_id); CREATE INDEX configinfo_groupid_key_idx ON config_info(group_id); CREATE INDEX configinfo_dataid_group_key_idx ON config_info(data_id, group_id); CREATE TABLE his_config_info ( - id bigint NOT NULL, - nid bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - op_type char(10) DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); + id bigint NOT NULL, + nid bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + publish_type varchar(50) DEFAULT 'formal', + ext_info CLOB, + op_type char(10) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); CREATE INDEX hisconfiginfo_dataid_key_idx ON his_config_info(data_id); CREATE INDEX hisconfiginfo_gmt_create_idx ON his_config_info(gmt_create); @@ -64,164 +66,174 @@ CREATE INDEX hisconfiginfo_gmt_modified_idx ON his_config_info(gmt_modified); CREATE TABLE config_info_beta ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - app_name varchar(128), - content CLOB, - beta_ips varchar(1024), - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - encrypted_data_key LONG VARCHAR DEFAULT NULL, - constraint configinfobeta_id_key PRIMARY KEY (id), - constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + beta_ips varchar(1024), + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfobeta_id_key PRIMARY KEY (id), + constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); CREATE TABLE config_info_tag ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - tag_id varchar(128) NOT NULL, - app_name varchar(128), - content CLOB, - md5 varchar(32) DEFAULT NULL, - gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - src_user varchar(128), - src_ip varchar(50) DEFAULT NULL, - constraint configinfotag_id_key PRIMARY KEY (id), - constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); - -CREATE TABLE config_info_aggr ( - id bigint NOT NULL generated by default as identity, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) default '', - datum_id varchar(255) NOT NULL, - app_name varchar(128), - content CLOB, - gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', - constraint configinfoaggr_id_key PRIMARY KEY (id), - constraint uk_configinfoaggr_datagrouptenantdatum UNIQUE (data_id,group_id,tenant_id,datum_id)); + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + tag_id varchar(128) NOT NULL, + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + constraint configinfotag_id_key PRIMARY KEY (id), + constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); + +CREATE TABLE config_info_gray ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + gray_name varchar(128) NOT NULL, + gray_rule CLOB, + app_name varchar(128), + src_ip varchar(128), + src_user varchar(128) default '', + content CLOB, + md5 varchar(32) DEFAULT NULL, + encrypted_data_key varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + constraint configinfogray_id_key PRIMARY KEY (id), + constraint uk_configinfogray_datagrouptenantgrayname UNIQUE (data_id,group_id,tenant_id,gray_name)); +CREATE INDEX config_info_gray_dataid_gmt_modified ON config_info_gray(data_id,gmt_modified); +CREATE INDEX config_info_gray_gmt_modified ON config_info_gray(gmt_modified); CREATE TABLE app_list ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - is_dynamic_collect_disabled smallint DEFAULT 0, - last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', - sub_info_lock_owner varchar(128), - sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', - constraint applist_id_key PRIMARY KEY (id), - constraint uk_appname UNIQUE (app_name)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + is_dynamic_collect_disabled smallint DEFAULT 0, + last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', + sub_info_lock_owner varchar(128), + sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', + constraint applist_id_key PRIMARY KEY (id), + constraint uk_appname UNIQUE (app_name)); CREATE TABLE app_configdata_relation_subs ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint configdatarelationsubs_id_key PRIMARY KEY (id), - constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationsubs_id_key PRIMARY KEY (id), + constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); CREATE TABLE app_configdata_relation_pubs ( - id bigint NOT NULL generated by default as identity, - app_name varchar(128) NOT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint configdatarelationpubs_id_key PRIMARY KEY (id), - constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationpubs_id_key PRIMARY KEY (id), + constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); CREATE TABLE config_tags_relation ( - id bigint NOT NULL, - tag_name varchar(128) NOT NULL, - tag_type varchar(64) DEFAULT NULL, - data_id varchar(255) NOT NULL, - group_id varchar(128) NOT NULL, - tenant_id varchar(128) DEFAULT '', - nid bigint NOT NULL generated by default as identity, - constraint config_tags_id_key PRIMARY KEY (nid), - constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); + id bigint NOT NULL, + tag_name varchar(128) NOT NULL, + tag_type varchar(64) DEFAULT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + nid bigint NOT NULL generated by default as identity, + constraint config_tags_id_key PRIMARY KEY (nid), + constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); CREATE INDEX config_tags_tenant_id_idx ON config_tags_relation(tenant_id); CREATE TABLE group_capacity ( - id bigint NOT NULL generated by default as identity, - group_id varchar(128) DEFAULT '', - quota int DEFAULT 0, - usage int DEFAULT 0, - max_size int DEFAULT 0, - max_aggr_count int DEFAULT 0, - max_aggr_size int DEFAULT 0, - max_history_count int DEFAULT 0, - gmt_create timestamp DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint group_capacity_id_key PRIMARY KEY (id), - constraint uk_group_id UNIQUE (group_id)); + id bigint NOT NULL generated by default as identity, + group_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint group_capacity_id_key PRIMARY KEY (id), + constraint uk_group_id UNIQUE (group_id)); CREATE TABLE tenant_capacity ( - id bigint NOT NULL generated by default as identity, - tenant_id varchar(128) DEFAULT '', - quota int DEFAULT 0, - usage int DEFAULT 0, - max_size int DEFAULT 0, - max_aggr_count int DEFAULT 0, - max_aggr_size int DEFAULT 0, - max_history_count int DEFAULT 0, - gmt_create timestamp DEFAULT '2010-05-05 00:00:00', - gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', - constraint tenant_capacity_id_key PRIMARY KEY (id), - constraint uk_tenant_id UNIQUE (tenant_id)); + id bigint NOT NULL generated by default as identity, + tenant_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint tenant_capacity_id_key PRIMARY KEY (id), + constraint uk_tenant_id UNIQUE (tenant_id)); CREATE TABLE tenant_info ( - id bigint NOT NULL generated by default as identity, - kp varchar(128) NOT NULL, - tenant_id varchar(128) DEFAULT '', - tenant_name varchar(128) DEFAULT '', - tenant_desc varchar(256) DEFAULT NULL, - create_source varchar(32) DEFAULT NULL, - gmt_create bigint NOT NULL, - gmt_modified bigint NOT NULL, - constraint tenant_info_id_key PRIMARY KEY (id), - constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); + id bigint NOT NULL generated by default as identity, + kp varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + tenant_name varchar(128) DEFAULT '', + tenant_desc varchar(256) DEFAULT NULL, + create_source varchar(32) DEFAULT NULL, + gmt_create bigint NOT NULL, + gmt_modified bigint NOT NULL, + constraint tenant_info_id_key PRIMARY KEY (id), + constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id); CREATE TABLE users ( - username varchar(50) NOT NULL PRIMARY KEY, - password varchar(500) NOT NULL, - enabled boolean NOT NULL DEFAULT true + username varchar(50) NOT NULL PRIMARY KEY, + password varchar(500) NOT NULL, + enabled boolean NOT NULL DEFAULT true ); CREATE TABLE roles ( - username varchar(50) NOT NULL, - role varchar(50) NOT NULL, - constraint uk_username_role UNIQUE (username,role) + username varchar(50) NOT NULL, + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) ); CREATE TABLE permissions ( - role varchar(50) NOT NULL, - resource varchar(512) NOT NULL, - action varchar(8) NOT NULL, - constraint uk_role_permission UNIQUE (role,resource,action) + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) ); + /******************************************/ /* ipv6 support */ /******************************************/ -ALTER TABLE `config_info_tag` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `his_config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL AFTER `src_user`; +ALTER TABLE config_info_tag ADD src_ip varchar(50) DEFAULT NULL; + +ALTER TABLE his_config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info ADD src_ip varchar(50) DEFAULT NULL ; + +ALTER TABLE config_info_beta ADD src_ip varchar(50) DEFAULT NULL ; -ALTER TABLE `config_info` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; -ALTER TABLE `config_info_beta` -MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; \ No newline at end of file +ALTER TABLE his_config_info ADD publish_type varchar(50) DEFAULT 'formal'; +ALTER TABLE his_config_info ADD ext_info CLOB DEFAULT NULL ;