Commit 66ebb71b8af77f13aa4ebaba1cd3623cc26294de

Authored by YunaiV
1 parent c64bb81c

Redis 最低版本 5.0.0 检测,解决搭建环境过程中无法理解 XREADGROUP 指令的报错

yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DocumentEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.common.enums;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 文档地址
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@Getter
  12 +@AllArgsConstructor
  13 +public enum DocumentEnum {
  14 +
  15 + REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档");
  16 +
  17 + private final String url;
  18 + private final String memo;
  19 +
  20 +}
... ...
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.mq.config;
2 2  
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.hutool.core.util.StrUtil;
3 5 import cn.hutool.system.SystemUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.DocumentEnum;
4 7 import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
5 8 import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;
6 9 import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
... ... @@ -10,10 +13,12 @@ import lombok.extern.slf4j.Slf4j;
10 13 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
11 14 import org.springframework.context.annotation.Bean;
12 15 import org.springframework.context.annotation.Configuration;
  16 +import org.springframework.data.redis.connection.RedisServerCommands;
13 17 import org.springframework.data.redis.connection.stream.Consumer;
14 18 import org.springframework.data.redis.connection.stream.ObjectRecord;
15 19 import org.springframework.data.redis.connection.stream.ReadOffset;
16 20 import org.springframework.data.redis.connection.stream.StreamOffset;
  21 +import org.springframework.data.redis.core.RedisCallback;
17 22 import org.springframework.data.redis.core.RedisTemplate;
18 23 import org.springframework.data.redis.core.StringRedisTemplate;
19 24 import org.springframework.data.redis.listener.ChannelTopic;
... ... @@ -22,6 +27,7 @@ import org.springframework.data.redis.stream.DefaultStreamMessageListenerContain
22 27 import org.springframework.data.redis.stream.StreamMessageListenerContainer;
23 28  
24 29 import java.util.List;
  30 +import java.util.Properties;
25 31  
26 32 /**
27 33 * 消息队列配置类
... ... @@ -73,6 +79,7 @@ public class YudaoMQAutoConfiguration {
73 79 public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(
74 80 RedisMQTemplate redisMQTemplate, List<AbstractStreamMessageListener<?>> listeners) {
75 81 RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate();
  82 + checkRedisVersion(redisTemplate);
76 83 // 第一步,创建 StreamMessageListenerContainer 容器
77 84 // 创建 options 配置
78 85 StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
... ... @@ -118,4 +125,19 @@ public class YudaoMQAutoConfiguration {
118 125 return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
119 126 }
120 127  
  128 + /**
  129 + * 校验 Redis 版本号,是否满足最低的版本号要求!
  130 + */
  131 + private static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
  132 + // 获得 Redis 版本
  133 + Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
  134 + String version = MapUtil.getStr(info, "redis_version");
  135 + // 校验最低版本必须大于等于 5.0.0
  136 + int majorVersion = Integer.parseInt(StrUtil.subBefore(version, '.', false));
  137 + if (majorVersion < 7) {
  138 + throw new IllegalStateException(StrUtil.format("您当前的 Redis 版本为 {},小于最低要求的 5.0.0 版本!" +
  139 + "请参考 {} 文档进行安装。", version, DocumentEnum.REDIS_INSTALL.getUrl()));
  140 + }
  141 + }
  142 +
121 143 }
... ...
yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java
1 1 package cn.iocoder.yudao.module.system.service.tenant;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO;
5 6 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO;
6 7 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO;
  8 +import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
7 9 import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO;
8 10 import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper;
9 11 import cn.iocoder.yudao.module.system.test.BaseDbUnitTest;
10 12 import org.junit.jupiter.api.Test;
  13 +import org.springframework.boot.test.mock.mockito.MockBean;
11 14 import org.springframework.context.annotation.Import;
12 15  
13 16 import javax.annotation.Resource;
14 17  
  18 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
15 19 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
16 20 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
17 21 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
18 22 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
19 23 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
20   -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_PACKAGE_NOT_EXISTS;
  24 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
  25 +import static java.util.Arrays.asList;
21 26 import static org.junit.jupiter.api.Assertions.*;
  27 +import static org.mockito.ArgumentMatchers.eq;
  28 +import static org.mockito.Mockito.verify;
  29 +import static org.mockito.Mockito.when;
22 30  
23 31 /**
24 32 * {@link TenantPackageServiceImpl} 的单元测试类
... ... @@ -34,6 +42,9 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest {
34 42 @Resource
35 43 private TenantPackageMapper tenantPackageMapper;
36 44  
  45 + @MockBean
  46 + private TenantService tenantService;
  47 +
37 48 @Test
38 49 public void testCreateTenantPackage_success() {
39 50 // 准备参数
... ... @@ -57,12 +68,21 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest {
57 68 TenantPackageUpdateReqVO reqVO = randomPojo(TenantPackageUpdateReqVO.class, o -> {
58 69 o.setId(dbTenantPackage.getId()); // 设置更新的 ID
59 70 });
  71 + // mock 方法
  72 + Long tenantId01 = randomLongId();
  73 + Long tenantId02 = randomLongId();
  74 + when(tenantService.getTenantListByPackageId(eq(reqVO.getId()))).thenReturn(
  75 + asList(randomPojo(TenantDO.class, o -> o.setId(tenantId01)),
  76 + randomPojo(TenantDO.class, o -> o.setId(tenantId02))));
60 77  
61 78 // 调用
62 79 tenantPackageService.updateTenantPackage(reqVO);
63 80 // 校验是否更新正确
64 81 TenantPackageDO tenantPackage = tenantPackageMapper.selectById(reqVO.getId()); // 获取最新的
65 82 assertPojoEquals(reqVO, tenantPackage);
  83 + // 校验调用租户的菜单
  84 + verify(tenantService).updateTenantRoleMenu(eq(tenantId01), eq(reqVO.getMenuIds()));
  85 + verify(tenantService).updateTenantRoleMenu(eq(tenantId02), eq(reqVO.getMenuIds()));
66 86 }
67 87  
68 88 @Test
... ... @@ -81,6 +101,8 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest {
81 101 tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
82 102 // 准备参数
83 103 Long id = dbTenantPackage.getId();
  104 + // mock 租户未使用该套餐
  105 + when(tenantService.getTenantCountByPackageId(eq(id))).thenReturn(0);
84 106  
85 107 // 调用
86 108 tenantPackageService.deleteTenantPackage(id);
... ... @@ -97,31 +119,45 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest {
97 119 assertServiceException(() -> tenantPackageService.deleteTenantPackage(id), TENANT_PACKAGE_NOT_EXISTS);
98 120 }
99 121  
100   - @Test // TODO 请修改 null 为需要的值
  122 + @Test
  123 + public void testDeleteTenantPackage_used() {
  124 + // mock 数据
  125 + TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class);
  126 + tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
  127 + // 准备参数
  128 + Long id = dbTenantPackage.getId();
  129 + // mock 租户在使用该套餐
  130 + when(tenantService.getTenantCountByPackageId(eq(id))).thenReturn(1);
  131 +
  132 + // 调用, 并断言异常
  133 + assertServiceException(() -> tenantPackageService.deleteTenantPackage(id), TENANT_PACKAGE_USED);
  134 + }
  135 +
  136 + @Test
101 137 public void testGetTenantPackagePage() {
102 138 // mock 数据
103 139 TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class, o -> { // 等会查询到
104   - o.setName(null);
105   - o.setStatus(null);
106   - o.setRemark(null);
107   - o.setCreateTime(null);
  140 + o.setName("芋道源码");
  141 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  142 + o.setRemark("源码解析");
  143 + o.setCreateTime(buildTime(2022, 10, 10));
108 144 });
109 145 tenantPackageMapper.insert(dbTenantPackage);
110 146 // 测试 name 不匹配
111   - tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setName(null)));
  147 + tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setName("源码")));
112 148 // 测试 status 不匹配
113   - tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setStatus(null)));
  149 + tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
114 150 // 测试 remark 不匹配
115   - tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setRemark(null)));
  151 + tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setRemark("解析")));
116 152 // 测试 createTime 不匹配
117   - tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setCreateTime(null)));
  153 + tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setCreateTime(buildTime(2022, 11, 11))));
118 154 // 准备参数
119 155 TenantPackagePageReqVO reqVO = new TenantPackagePageReqVO();
120   - reqVO.setName(null);
121   - reqVO.setStatus(null);
122   - reqVO.setRemark(null);
123   - reqVO.setBeginCreateTime(null);
124   - reqVO.setEndCreateTime(null);
  156 + reqVO.setName("芋道");
  157 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  158 + reqVO.setRemark("源码");
  159 + reqVO.setBeginCreateTime(buildTime(2022, 10, 9));
  160 + reqVO.setEndCreateTime(buildTime(2022, 10, 11));
125 161  
126 162 // 调用
127 163 PageResult<TenantPackageDO> pageResult = tenantPackageService.getTenantPackagePage(reqVO);
... ... @@ -131,4 +167,37 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest {
131 167 assertPojoEquals(dbTenantPackage, pageResult.getList().get(0));
132 168 }
133 169  
  170 + @Test
  171 + public void testValidTenantPackage_success() {
  172 + // mock 数据
  173 + TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class,
  174 + o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
  175 + tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
  176 +
  177 + // 调用
  178 + TenantPackageDO result = tenantPackageService.validTenantPackage(dbTenantPackage.getId());
  179 + // 断言
  180 + assertPojoEquals(dbTenantPackage, result);
  181 + }
  182 +
  183 + @Test
  184 + public void testValidTenantPackage_notExists() {
  185 + // 准备参数
  186 + Long id = randomLongId();
  187 +
  188 + // 调用, 并断言异常
  189 + assertServiceException(() -> tenantPackageService.validTenantPackage(id), TENANT_PACKAGE_NOT_EXISTS);
  190 + }
  191 +
  192 + @Test
  193 + public void testValidTenantPackage_disable() {
  194 + // mock 数据
  195 + TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class,
  196 + o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
  197 + tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据
  198 +
  199 + // 调用, 并断言异常
  200 + assertServiceException(() -> tenantPackageService.validTenantPackage(dbTenantPackage.getId()),
  201 + TENANT_PACKAGE_DISABLE, dbTenantPackage.getName());
  202 + }
134 203 }
... ...
yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceTest.java renamed to yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java
1 1 package cn.iocoder.yudao.module.system.service.tenant;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
3 6 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO;
4 7 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
5 8 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
6 9 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO;
7 10 import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
8 11 import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
9   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
10   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
  12 +import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer;
  13 +import cn.iocoder.yudao.module.system.service.permission.MenuService;
  14 +import cn.iocoder.yudao.module.system.service.permission.PermissionService;
  15 +import cn.iocoder.yudao.module.system.service.permission.RoleService;
  16 +import cn.iocoder.yudao.module.system.service.user.AdminUserService;
11 17 import cn.iocoder.yudao.module.system.test.BaseDbUnitTest;
12 18 import org.junit.jupiter.api.Test;
  19 +import org.springframework.boot.test.mock.mockito.MockBean;
13 20 import org.springframework.context.annotation.Import;
14 21  
15 22 import javax.annotation.Resource;
16 23 import java.util.List;
17 24  
18   -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS;
19 25 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
20 26 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
21 27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
22 28 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
23 29 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  30 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS;
24 31 import static org.junit.jupiter.api.Assertions.*;
25 32  
  33 +/**
  34 + * {@link TenantServiceImpl} 的单元测试类
  35 + *
  36 + * @author 芋道源码
  37 + */
26 38 @Import(TenantServiceImpl.class)
27   -public class TenantServiceTest extends BaseDbUnitTest {
  39 +public class TenantServiceImplTest extends BaseDbUnitTest {
28 40  
29 41 @Resource
30 42 private TenantServiceImpl tenantService;
... ... @@ -32,6 +44,21 @@ public class TenantServiceTest extends BaseDbUnitTest {
32 44 @Resource
33 45 private TenantMapper tenantMapper;
34 46  
  47 + @MockBean
  48 + private TenantProperties tenantProperties;
  49 + @MockBean
  50 + private TenantPackageService tenantPackageService;
  51 + @MockBean
  52 + private AdminUserService userService;
  53 + @MockBean
  54 + private RoleService roleService;
  55 + @MockBean
  56 + private MenuService menuService;
  57 + @MockBean
  58 + private PermissionService permissionService;
  59 + @MockBean
  60 + private TenantProducer tenantProducer;
  61 +
35 62 @Test
36 63 public void testCreateTenant_success() {
37 64 // 准备参数
... ...
更新日志.md
... ... @@ -32,6 +32,7 @@ TODO
32 32 * 【新增】新增 `@TenantIgnore` 注解,标记指定方法,忽略多租户的自动过滤,适合实现跨租户的逻辑 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/4d53944771c66b563da1e3d68d3ba43405af8a06)
33 33 * 【新增】租户套餐的管理,可配置每个租户的可使用的功能权限 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/6b6d676a6baa2dad16ae9bf03d5002209064c8cc)
34 34 * 【优化】新建租户时,自动创建对应的管理员账号、角色等基础信息 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/2598c033a95d4b61d5f5ab3da5f1414f25c510d6)
  35 +* 【优化】Redis 最低版本 5.0.0 检测,解决搭建环境过程中无法理解 XREADGROUP 指令的报错 [commit]()
35 36  
36 37 ### 🐞 Bug Fixes
37 38  
... ...