diff --git a/core/src/main/java/com/ctrip/xpipe/cluster/ClusterType.java b/core/src/main/java/com/ctrip/xpipe/cluster/ClusterType.java
index e3d5f471d..62c8ef39c 100644
--- a/core/src/main/java/com/ctrip/xpipe/cluster/ClusterType.java
+++ b/core/src/main/java/com/ctrip/xpipe/cluster/ClusterType.java
@@ -100,6 +100,13 @@ public static boolean supportUpgradeAzGroup(String type) {
|| isSameClusterType(type, SINGLE_DC);
}
+ public static boolean supportConvert(String type) {
+ if (StringUtil.isEmpty(type)) {
+ return false;
+ }
+ return isSameClusterType(type, ONE_WAY) || isSameClusterType(type, HETERO);
+ }
+
public static ClusterType lookup(String name) {
if (StringUtil.isEmpty(name)) throw new IllegalArgumentException("no ClusterType for name " + name);
return valueOf(name.toUpperCase());
diff --git a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateController.java b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateController.java
index 7148115c3..2758a485f 100644
--- a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateController.java
+++ b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateController.java
@@ -277,6 +277,12 @@ public RetMessage upgradeAzGroup(@PathVariable String clusterName) {
return RetMessage.createSuccessMessage();
}
+ @DeleteMapping(value = "/clusters/" + CLUSTER_NAME_PATH_VARIABLE + "/azGroup")
+ public RetMessage downgradeAzGroup(@PathVariable String clusterName) {
+ clusterService.downgradeAzGroup(clusterName);
+ return RetMessage.createSuccessMessage();
+ }
+
@PostMapping(value = "/clusters/" + CLUSTER_NAME_PATH_VARIABLE + "/dcs/{dcName}")
public RetMessage bindDc(@PathVariable String clusterName, @PathVariable String dcName,
@RequestBody(required = false) DcDetailInfo dcDetailInfo) {
diff --git a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/entity/AzGroupClusterEntity.java b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/entity/AzGroupClusterEntity.java
index 36604612f..b815e300b 100644
--- a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/entity/AzGroupClusterEntity.java
+++ b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/entity/AzGroupClusterEntity.java
@@ -14,7 +14,7 @@
*
*
* @author mybatis-generator
- * @since 2023-07-10
+ * @since 2023-11-14
*/
@TableName("az_group_cluster_tbl")
public class AzGroupClusterEntity extends BaseEntity {
@@ -57,6 +57,12 @@ public class AzGroupClusterEntity extends BaseEntity {
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
+ /**
+ * 逻辑删除时间
+ */
+ @TableField("delete_time")
+ private Date deleteTime;
+
public Long getId() {
return id;
}
@@ -111,6 +117,15 @@ public AzGroupClusterEntity setCreateTime(Date createTime) {
return this;
}
+ public Date getDeleteTime() {
+ return deleteTime;
+ }
+
+ public AzGroupClusterEntity setDeleteTime(Date deleteTime) {
+ this.deleteTime = deleteTime;
+ return this;
+ }
+
public static final String ID = "id";
public static final String CLUSTER_ID = "cluster_id";
@@ -123,10 +138,12 @@ public AzGroupClusterEntity setCreateTime(Date createTime) {
public static final String CREATE_TIME = "create_time";
+ public static final String DELETE_TIME = "delete_time";
+
@Override
public String toString() {
return "AzGroupClusterEntity{" + "id = " + id + ", clusterId = " + clusterId + ", azGroupId = " + azGroupId
+ ", activeAzId = " + activeAzId + ", azGroupClusterType = " + azGroupClusterType + ", createTime = "
- + createTime + "}";
+ + createTime + ", deleteTime = " + deleteTime + "}";
}
}
diff --git a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/repository/AzGroupClusterRepository.java b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/repository/AzGroupClusterRepository.java
index c63e3f883..353df7f8c 100644
--- a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/repository/AzGroupClusterRepository.java
+++ b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/repository/AzGroupClusterRepository.java
@@ -13,6 +13,7 @@
import javax.annotation.Resource;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
@Repository
@@ -148,17 +149,24 @@ public void deleteByClusterId(Long clusterId) {
if (clusterId == null) {
return;
}
- QueryWrapper wrapper = new QueryWrapper<>();
+ UpdateWrapper wrapper = new UpdateWrapper<>();
+ wrapper.set(AzGroupClusterEntity.DELETED, 1);
+ wrapper.set(AzGroupClusterEntity.DELETE_TIME, new Date());
+
wrapper.eq(AzGroupClusterEntity.CLUSTER_ID, clusterId);
- azGroupClusterMapper.delete(wrapper);
+ azGroupClusterMapper.update(null, wrapper);
}
public void deleteByClusterIdAndAzGroupId(Long clusterId, Long azGroupId) {
if (clusterId == null || azGroupId == null) {
return;
}
- QueryWrapper wrapper = new QueryWrapper<>();
- wrapper.eq(AzGroupClusterEntity.CLUSTER_ID, clusterId).eq(AzGroupClusterEntity.AZ_GROUP_ID, azGroupId);
- azGroupClusterMapper.delete(wrapper);
+ UpdateWrapper wrapper = new UpdateWrapper<>();
+ wrapper.set(AzGroupClusterEntity.DELETED, 1);
+ wrapper.set(AzGroupClusterEntity.DELETE_TIME, new Date());
+
+ wrapper.eq(AzGroupClusterEntity.CLUSTER_ID, clusterId);
+ wrapper.eq(AzGroupClusterEntity.AZ_GROUP_ID, azGroupId);
+ azGroupClusterMapper.update(null, wrapper);
}
}
diff --git a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/ClusterService.java b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/ClusterService.java
index 03c60805e..d15760374 100644
--- a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/ClusterService.java
+++ b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/ClusterService.java
@@ -55,6 +55,7 @@ public interface ClusterService {
void exchangeName(Long formerClusterId, String formerClusterName, Long latterClusterId, String latterClusterName);
void exchangeRegion(Long formerClusterId, String formerClusterName, Long latterClusterId, String latterClusterName, String regionName);
void upgradeAzGroup(String clusterName);
+ void downgradeAzGroup(String clusterName);
void bindRegionAz(String clusterName, String regionName, String azName);
Set findMigratingClusterNames();
diff --git a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/impl/ClusterServiceImpl.java b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/impl/ClusterServiceImpl.java
index 3d213aafc..e4004398d 100644
--- a/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/impl/ClusterServiceImpl.java
+++ b/redis/redis-console/src/main/java/com/ctrip/xpipe/redis/console/service/impl/ClusterServiceImpl.java
@@ -654,49 +654,47 @@ private List setOrgNullIfNoOrgIdExsits(List clusterTblLi
return clusterTblList;
}
- @Override
- public String updateCluster(ClusterUpdateDTO clusterUpdateDTO) {
- String clusterName = clusterUpdateDTO.getClusterName();
- ClusterTbl clusterTbl = clusterDao.findClusterByClusterName(clusterName);
- if (clusterTbl == null) {
- throw new BadRequestException("Not find cluster: " + clusterName);
- }
+ @Override
+ public String updateCluster(ClusterUpdateDTO clusterUpdateDTO) {
+ String clusterName = clusterUpdateDTO.getClusterName();
+ ClusterTbl clusterTbl = clusterDao.findClusterByClusterName(clusterName);
+ if (clusterTbl == null) {
+ throw new BadRequestException("Not find cluster: " + clusterName);
+ }
boolean needUpdate = false;
- ClusterType clusterType = StringUtils.isEmpty(clusterUpdateDTO.getClusterType())
- ? null : ClusterType.lookup(clusterUpdateDTO.getClusterType());
- if (clusterType != null) {
+ String clusterType = clusterUpdateDTO.getClusterType();
+ if (!StringUtil.isEmpty(clusterType)) {
String oldClusterType = clusterTbl.getClusterType();
- if (!ClusterType.isSameClusterType(oldClusterType, clusterType)) {
- if (ClusterType.isSameClusterType(oldClusterType, ClusterType.ONE_WAY)
- && clusterType == ClusterType.HETERO) {
+ if (!clusterType.equalsIgnoreCase(oldClusterType)) {
+ if (ClusterType.supportConvert(oldClusterType) && ClusterType.supportConvert(clusterType)) {
needUpdate = true;
- clusterTbl.setClusterType(clusterType.toString());
+ clusterTbl.setClusterType(clusterType.toUpperCase());
} else {
- // 仅允许单向同步集群改为异构集群
- throw new BadRequestException("Only ONE_WAY cluster can change type to HETERO");
+ // 仅允许单向同步、异构集群之间互相转换
+ throw new BadRequestException("Only ONE_WAY/HETERO cluster can be converted to each other");
}
}
}
Long orgId = clusterUpdateDTO.getOrgId();
- if (!Objects.equals(orgId, clusterTbl.getClusterOrgId())) {
+ if (orgId != null && !Objects.equals(orgId, clusterTbl.getClusterOrgId())) {
needUpdate = true;
clusterTbl.setClusterOrgId(orgId);
}
String adminEmails = clusterUpdateDTO.getAdminEmails();
- if (!Objects.equals(adminEmails, clusterTbl.getClusterAdminEmails())) {
+ if (adminEmails != null && !Objects.equals(adminEmails, clusterTbl.getClusterAdminEmails())) {
needUpdate = true;
clusterTbl.setClusterAdminEmails(adminEmails);
}
- if (needUpdate) {
- clusterDao.updateCluster(clusterTbl);
- return RetMessage.SUCCESS;
- } else {
- return String.format("No field changes for cluster: %s", clusterName);
- }
- }
+ if (needUpdate) {
+ clusterDao.updateCluster(clusterTbl);
+ return RetMessage.SUCCESS;
+ } else {
+ return String.format("No field changes for cluster: %s", clusterName);
+ }
+ }
@Override
@DalTransaction
@@ -1064,7 +1062,7 @@ public Integer doQuery() throws DalException {
@Override
@Transactional
public void upgradeAzGroup(String clusterName) {
- ClusterTbl cluster = clusterDao.findClusterByClusterName(clusterName);
+ ClusterEntity cluster = clusterRepository.selectByClusterName(clusterName);
if (cluster == null) {
throw new BadRequestException(String.format("Cluster: %s not exist", clusterName));
}
@@ -1126,6 +1124,34 @@ public void upgradeAzGroup(String clusterName) {
}
}
+ @Override
+ @Transactional
+ public void downgradeAzGroup(String clusterName) {
+ ClusterEntity cluster = clusterRepository.selectByClusterName(clusterName);
+ if (cluster == null) {
+ throw new BadRequestException(String.format("Cluster: %s not exist", clusterName));
+ }
+ Long clusterId = cluster.getId();
+ List azGroupClusters = azGroupClusterRepository.selectByClusterId(clusterId);
+ if (CollectionUtils.isEmpty(azGroupClusters)) {
+ logger.warn("Cluster: {} not in AzGroup mode", clusterName);
+ return;
+ }
+ if (azGroupClusters.size() > 1) {
+ throw new BadRequestException(
+ String.format("Cluster: %s contains multi az group, cannot downgrade", clusterName));
+ }
+ azGroupClusterRepository.deleteByClusterId(clusterId);
+
+ List dcClusters = dcClusterRepository.selectByClusterId(clusterId);
+ List dcClusterIds = dcClusters.stream().map(DcClusterEntity::getDcClusterId).collect(Collectors.toList());
+ dcClusterRepository.batchUpdateAzGroupClusterId(dcClusterIds, 0L);
+
+ List shards = shardRepository.selectByClusterId(clusterId);
+ List shardIds = shards.stream().map(ShardEntity::getId).collect(Collectors.toList());
+ shardRepository.batchUpdateAzGroupClusterId(shardIds, 0L);
+ }
+
@Override
@DalTransaction
public void exchangeName(Long formerClusterId, String formerClusterName, Long latterClusterId, String latterClusterName) {
diff --git a/redis/redis-console/src/main/resources/sql/h2/xpipedemodbtables.sql b/redis/redis-console/src/main/resources/sql/h2/xpipedemodbtables.sql
index deaf05aea..56bde1add 100644
--- a/redis/redis-console/src/main/resources/sql/h2/xpipedemodbtables.sql
+++ b/redis/redis-console/src/main/resources/sql/h2/xpipedemodbtables.sql
@@ -112,6 +112,7 @@ CREATE TABLE `AZ_GROUP_CLUSTER_TBL` (
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time',
`DataChange_LastTime` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'last modify time',
`deleted` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'logic delete',
+ `delete_time` timestamp NOT NULL DEFAULT '2003-12-09 09:30:00' COMMENT 'logic delete time',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_cluster_az_group` (`cluster_id`,`az_group_id`)
);
diff --git a/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/MybatisGeneratorTest.java b/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/MybatisGeneratorTest.java
index 75a1d8c4b..65547388f 100644
--- a/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/MybatisGeneratorTest.java
+++ b/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/MybatisGeneratorTest.java
@@ -52,7 +52,7 @@ protected static PackageConfig packageConfig() {
*/
protected static StrategyConfig strategyConfig() {
return new StrategyConfig.Builder()
- .addInclude("cluster_tbl", "shard_tbl")
+ .addInclude("az_group_cluster_tbl")
// 删除tbl后缀
.addTableSuffix("_tbl")
.entityBuilder()
diff --git a/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateControllerTest.java b/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateControllerTest.java
index 50066d813..fa8f6b1f0 100644
--- a/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateControllerTest.java
+++ b/redis/redis-console/src/test/java/com/ctrip/xpipe/redis/console/controller/api/data/ClusterUpdateControllerTest.java
@@ -203,19 +203,28 @@ public void updateCluster() {
clusterInfo.setClusterName(clusterName);
clusterInfo.setClusterType(ClusterType.HETERO.toString());
clusterInfo.setDesc(desc);
- clusterInfo.setOrganizationId(orgId);
- clusterInfo.setClusterAdminEmails(adminEmails);
RetMessage retMessage = clusterController.updateCluster(clusterInfo);
logger.info("{}", retMessage.getMessage());
Assert.assertEquals(RetMessage.SUCCESS_STATE, retMessage.getState());
ClusterTbl cluster = clusterDao.findClusterAndOrgByName(clusterName);
- Assert.assertEquals(orgId, cluster.getOrganizationInfo().getOrgId());
+ Assert.assertEquals(ClusterType.HETERO.toString(), cluster.getClusterType());
// 目前api接口不更新desc
Assert.assertEquals("", cluster.getClusterDescription());
+ Assert.assertEquals(0L, cluster.getClusterOrgId());
+ Assert.assertNull(cluster.getClusterAdminEmails());
+
+ clusterInfo.setOrganizationId(orgId);
+ clusterController.updateCluster(clusterInfo);
+ cluster = clusterDao.findClusterAndOrgByName(clusterName);
+ Assert.assertEquals(orgId, cluster.getOrganizationInfo().getOrgId());
+ Assert.assertNull(cluster.getClusterAdminEmails());
+
+ clusterInfo.setClusterAdminEmails(adminEmails);
+ clusterController.updateCluster(clusterInfo);
+ cluster = clusterDao.findClusterAndOrgByName(clusterName);
Assert.assertEquals(adminEmails, cluster.getClusterAdminEmails());
- Assert.assertEquals(ClusterType.HETERO.toString(), cluster.getClusterType());
}
@Test
@@ -404,6 +413,17 @@ public void testUpgradeBiClusterToAzGroup() {
Assert.assertEquals(Collections.singletonList("oy"), region2.getAzs());
}
+ @Test
+ public void testDowngradeAzGroupToOnewayCluster() {
+ this.createCluster(null, "HETERO", Arrays.asList("jq", "oy", "fra"), Arrays.asList(region1, region2));
+ clusterController.unbindDc("cluster-name", "fra");
+
+ clusterController.downgradeAzGroup("cluster-name");
+ ClusterCreateInfo cluster = clusterController.getCluster("cluster-name");
+ Assert.assertEquals(0, cluster.getRegions().size());
+ Assert.assertEquals(Arrays.asList("jq", "oy"), cluster.getDcs());
+ }
+
@Test
public void testBindDc() {
this.createCluster(null, null, null, null);