public void registerAndPush(int configId, int envId) {
   Config config = getConfig(configId);
   if (config == null) {
     throw new EntityNotFoundException("config[id=" + configId + "] not found, maybe deleted.");
   }
   ConfigInstance defaultInst = findDefaultInstance(configId, envId);
   if (defaultInst == null) {
     throw new RuntimeBusinessException("该环境下配置项不存在!");
   }
   try {
     ConfigRegisterService registerService = getRegisterService(envId);
     // register context value需要放在register default value前面,重要的操作在后面,确保zk与db数据一致,大部分配置无context value
     // 第一个注册操作就需要push,第二个不需要,确保第一个操作时客户端感知到变化时就已经感知到了push事务
     registerService.registerAndPushContextValue(
         config.getKey(), getConfigContextValue(configId, envId));
     registerService.registerDefaultValue(
         config.getKey(), resolveConfigFinalValue(defaultInst.getValue(), envId));
   } catch (RuntimeException e) {
     Environment environment = environmentService.findEnvByID(envId);
     logger.error(
         "Register and push config["
             + config.getKey()
             + "] to env["
             + (environment != null ? environment.getLabel() : envId)
             + "] failed.",
         e);
     throw e;
   }
 }
 @Override
 public String getConfigContextValue(int configId, int envId) {
   try {
     List<ConfigInstance> topInsts =
         configDao.findInstanceByConfig(configId, envId, ServiceConstants.MAX_AVAIL_CONFIG_INST);
     if (!topInsts.isEmpty()) {
       Iterator<ConfigInstance> iterator = topInsts.iterator();
       while (iterator.hasNext()) {
         ConfigInstance inst = iterator.next();
         if (inst.isDefault()) {
           iterator.remove();
           break;
         }
       }
     }
     JSONArray valueArray = new JSONArray();
     for (ConfigInstance topInst : topInsts) {
       JSONObject valueObj = new JSONObject();
       valueObj.put("value", resolveConfigFinalValue(topInst.getValue(), envId));
       valueObj.put("context", topInst.getContext());
       valueArray.put(valueObj);
     }
     return valueArray.toString();
   } catch (JSONException e) {
     Config config = getConfig(configId);
     throw new RuntimeBusinessException(
         "Cannot create config[key="
             + config.getKey()
             + "]'s register value, "
             + "plz check its instances' value.",
         e);
   }
 }
 private void updateReferencedInstances(
     Config config, List<ConfigInstance> refInstances, ConfigSetType setType) {
   try {
     for (ConfigInstance refInstance : refInstances) {
       int envId = refInstance.getEnvId();
       try {
         if (setType == ConfigSetType.RegisterAndPush) {
           registerAndPush(refInstance.getConfigId(), envId);
         } else if (setType == ConfigSetType.Register) {
           register(refInstance.getConfigId(), envId);
         }
       } catch (RuntimeException e) {
         Config refconfig = getConfig(refInstance.getConfigId());
         operationLogService.createOpLog(
             new OperationLog(
                     OperationTypeEnum.Config_Edit,
                     config.getProjectId(),
                     envId,
                     "同步更新关联引用配置项["
                         + (refconfig != null ? refconfig.getKey() : refInstance.getConfigId())
                         + "]出错,请重新保存该配置.")
                 .key(config.getKey(), ConfigInstance.NO_CONTEXT));
       }
     }
   } catch (Exception e) {
     logger.error("Update config[" + config.getKey() + "]'s referenced configs failed.", e);
   }
 }
 @Override
 public List<ConfigInstance> findInstancesByConfig(int configId, Integer maxPerEnv) {
   Config config = getConfig(configId);
   if (config == null) {
     return Collections.emptyList();
   }
   return configDao.findInstanceByConfig(config.getId(), maxPerEnv);
 }
 public void deleteInstance(Config config, int envId) {
   if (hasConfigReferencedTo(config.getKey(), envId)) {
     throw new ReferencedConfigForbidDeleteException(config.getKey());
   }
   configDao.deleteInstance(config.getId(), envId);
   configDao.deleteStatus(config.getId(), envId);
   getRegisterService(envId).unregister(config.getKey());
 }
 public int updateConfig(Config config) {
   try {
     config.setModifyUserId(SecurityUtils.getCurrentUserId());
     return configDao.update(config);
   } finally {
     cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getId());
     cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getKey());
   }
 }
  public int createInstance(ConfigInstance instance, ConfigSetType setType) {
    Integer currentUserId = SecurityUtils.getCurrentUserId();
    if (instance.getCreateUserId() == null) {
      instance.setCreateUserId(currentUserId);
    }
    if (instance.getModifyUserId() == null) {
      instance.setModifyUserId(currentUserId);
    }
    processInstanceIfReferenceType(instance);
    int retryTimes = 0;
    while (true) {
      try {
        instance.setSeq(configDao.getMaxInstSeq(instance.getConfigId(), instance.getEnvId()) + 1);
        int instId = configDao.createInstance(instance);
        updateConfigModifyStatus(instance.getConfigId(), instance.getEnvId());

        Config config = getConfig(instance.getConfigId());
        List<ConfigInstance> refInstances =
            getInstanceReferencedTo(config.getKey(), instance.getEnvId());

        // 确保注册操作是在最后一步
        if (setType == ConfigSetType.RegisterAndPush) {
          registerAndPush(instance.getConfigId(), instance.getEnvId());
        } else if (setType == ConfigSetType.Register) {
          register(instance.getConfigId(), instance.getEnvId());
        }

        updateReferencedInstances(config, refInstances, setType);

        return instId;
      } catch (RuntimeException e) {
        if (DBUtils.isDuplicateKeyError(e)) {
          if (retryTimes++ >= 1) {
            String errorMsg =
                StringUtils.isNotBlank(instance.getContext())
                    ? "该上下文[context]下配置值已存在!"
                    : "默认配置值已存在!";
            throw new RuntimeBusinessException(errorMsg);
          }
        } else {
          throw e;
        }
      }
    }
  }
  private int updateInstance(ConfigInstance instance, ConfigSetType setType) {
    instance.setModifyUserId(SecurityUtils.getCurrentUserId());
    processInstanceIfReferenceType(instance);
    int instId = configDao.updateInstance(instance);
    updateConfigModifyStatus(instance.getConfigId(), instance.getEnvId());

    Config config = getConfig(instance.getConfigId());
    List<ConfigInstance> refInstances =
        getInstanceReferencedTo(config.getKey(), instance.getEnvId());

    // 确保注册操作是在最后一步(后续的都需要try-catch掉所有error)
    if (setType == ConfigSetType.RegisterAndPush) {
      registerAndPush(instance.getConfigId(), instance.getEnvId());
    } else if (setType == ConfigSetType.Register) {
      register(instance.getConfigId(), instance.getEnvId());
    }

    updateReferencedInstances(config, refInstances, setType);
    return instId;
  }
 @Override
 public ConfigDeleteResult delete(int configId) {
   final ConfigDeleteResult result = new ConfigDeleteResult();
   final Config config = getConfig(configId);
   if (config != null) {
     result.setConfig(config);
     List<Environment> environments = environmentService.findAll();
     for (final Environment environment : environments) {
       try {
         this.transactionTemplate.execute(
             new TransactionCallbackWithoutResult() {
               @Override
               protected void doInTransactionWithoutResult(TransactionStatus status) {
                 deleteInstance(config, environment.getId());
               }
             });
       } catch (RuntimeException e) {
         logger.error(
             "Delete config["
                 + config.getKey()
                 + "] in environment["
                 + environment.getLabel()
                 + "] failed.",
             e);
         result.addFailedEnv(environment.getLabel());
         if (e instanceof ReferencedConfigForbidDeleteException) {
           result.setHasReference(true);
         }
       }
     }
     if (result.isSucceed()) {
       configDao.delete(configId);
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + configId);
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getKey());
     }
   }
   return result;
 }
 @Override
 public void moveUp(int projectId, Integer configId) {
   Config config = getConfig(configId);
   if (config == null) {
     throw new EntityNotFoundException("Config[id=" + configId + "] not found.");
   }
   projectDao.lockProject(projectId);
   Config prevConfig = configDao.getPrevConfig(configId);
   if (prevConfig != null) {
     try {
       int seq = config.getSeq();
       config.setSeq(prevConfig.getSeq());
       prevConfig.setSeq(seq);
       configDao.update(config);
       configDao.update(prevConfig);
     } finally {
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getId());
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getKey());
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + prevConfig.getId());
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + prevConfig.getKey());
     }
   }
 }
 @Override
 public void moveDown(int projectId, int configId) {
   Config config = getConfig(configId);
   if (config == null) {
     throw new EntityNotFoundException("Config[id=" + configId + "] not found.");
   }
   projectDao.lockProject(projectId); // 锁定指定projectId,避免同一项目下的config出现相同的seq值
   Config nextConfig = configDao.getNextConfig(configId);
   if (nextConfig != null) {
     try {
       int seq = config.getSeq();
       config.setSeq(nextConfig.getSeq());
       nextConfig.setSeq(seq);
       configDao.update(config);
       configDao.update(nextConfig);
     } finally {
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getId());
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + config.getKey());
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + nextConfig.getId());
       cacheClient.remove(ServiceConstants.CACHE_CONFIG_PREFIX + nextConfig.getKey());
     }
   }
 }
 @Override
 public List<ConfigVo> findConfigVos(ConfigCriteria criteria) {
   int projectId = criteria.getProjectId();
   int envId = criteria.getEnvId();
   HasValueEnum hasValue =
       EnumUtils.fromEnumProperty(HasValueEnum.class, "value", criteria.getHasValue());
   List<Config> configs = configDao.findConfigByProject(projectId);
   List<ConfigVo> configVos = new ArrayList<ConfigVo>(configs.size());
   if (!configs.isEmpty()) {
     List<Integer> hasInstanceConfigs = configDao.findHasInstanceConfigs(projectId, envId);
     List<Integer> hasContextInstConfigs = configDao.findHasContextInstConfigs(projectId, envId);
     Map<Integer, ConfigInstance> defaultInsts = configDao.findDefaultInstance(projectId, envId);
     List<Integer> hasReferencedConfigs =
         isSharedProject(projectId)
             ? configDao.getProjectHasReferencedConfigs(projectId)
             : Collections.<Integer>emptyList();
     for (Config config : configs) {
       // 配置不会太多,使用内存过滤,无分页,如果配置太多影响到性能则考虑数据库过滤和分页
       String key = StringUtils.trim(criteria.getKey());
       String value = StringUtils.trim(criteria.getValue());
       ConfigInstance defaultInst = defaultInsts.get(config.getId());
       if ((StringUtils.isEmpty(key) || config.getKey().contains(key))
           && (hasValue == HasValueEnum.All
               || (hasValue == HasValueEnum.Yes && defaultInst != null)
               || (hasValue == HasValueEnum.No && defaultInst == null))
           && (StringUtils.isEmpty(value)
               || (defaultInst != null && defaultInst.getValue().contains(value)))) {
         configVos.add(
             new ConfigVo(
                 config,
                 hasInstanceConfigs.contains(config.getId()),
                 hasContextInstConfigs.contains(config.getId()),
                 hasReferencedConfigs.contains(config.getId()),
                 defaultInst));
       }
     }
   }
   return configVos;
 }
 @Override
 public void setConfigValue(
     int projectId,
     int envId,
     String key,
     String desc,
     String context,
     String value,
     ConfigSetType setType) {
   Config config = findConfigByKey(key);
   int configId = 0;
   if (config == null) {
     config = new Config();
     config.setKey(key);
     config.setDesc(desc);
     config.setTypeEnum(ConfigTypeEnum.String);
     config.setProjectId(projectId);
     configId = create(config);
   } else {
     configId = config.getId();
   }
   setConfigValue(configId, envId, context, value, setType);
 }
 @Override
 public int create(Config config) {
   Config configFound = configDao.findConfigByKey(config.getKey());
   if (configFound != null) {
     Project project = projectDao.getProject(configFound.getProjectId());
     throw new RuntimeBusinessException(
         "该配置项已存在(project: "
             + (project != null ? project.getName() : "***")
             + ", desc: "
             + configFound.getDesc()
             + ")!");
   }
   Integer currentUserId = SecurityUtils.getCurrentUserId();
   int projectId = config.getProjectId();
   if (config.getCreateUserId() == null) {
     config.setCreateUserId(currentUserId);
   }
   if (config.getModifyUserId() == null) {
     config.setModifyUserId(currentUserId);
   }
   projectDao.lockProject(projectId);
   if (!config.isPrivatee()) {
     config.setPrivatee(isSharedProject(projectId));
   }
   config.setSeq(configDao.getMaxSeq(projectId) + 1);
   return configDao.create(config);
 }