Merge remote-tracking branch 'origin/master'

This commit is contained in:
YunaiV
2023-01-25 10:51:25 +08:00
35 changed files with 204 additions and 718 deletions

View File

@@ -6,15 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime;
/**
* 文件配置 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
@@ -26,7 +18,4 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
.orderByDesc(FileConfigDO::getId));
}
@Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}")
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
}

View File

@@ -23,7 +23,7 @@ public class FileConfigRefreshConsumer {
@EventListener
public void execute(FileConfigRefreshMessage message) {
log.info("[execute][收到 FileConfig 刷新消息]");
fileConfigService.initFileClients();
fileConfigService.initLocalCache();
}
}

View File

@@ -21,7 +21,7 @@ public interface FileConfigService {
/**
* 初始化文件客户端
*/
void initFileClients();
void initLocalCache();
/**
* 创建文件配置

View File

@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.service.file;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.file.core.client.FileClient;
@@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
@@ -29,7 +27,6 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -48,18 +45,6 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG
@Slf4j
public class FileConfigServiceImpl implements FileConfigService {
/**
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
*/
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
/**
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
*/
@Getter
private volatile LocalDateTime maxUpdateTime;
@Resource
private FileClientFactory fileClientFactory;
/**
@@ -79,34 +64,12 @@ public class FileConfigServiceImpl implements FileConfigService {
@Override
@PostConstruct
public void initFileClients() {
initLocalCacheIfUpdate(null);
}
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
public void schedulePeriodicRefresh() {
initLocalCacheIfUpdate(this.maxUpdateTime);
}
/**
* 刷新本地缓存
*
* @param maxUpdateTime 最大更新时间
* 1. 如果 maxUpdateTime 为 null则“强制”刷新缓存
* 2. 如果 maxUpdateTime 不为 null判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
*/
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
// 如果没有增量的数据变化,则不进行本地缓存的刷新
if (maxUpdateTime != null
&& fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
return;
}
public void initLocalCache() {
// 第一步:查询数据
List<FileConfigDO> configs = fileConfigMapper.selectList();
log.info("[initLocalCacheIfUpdate][缓存文件配置,数量为:{}]", configs.size());
log.info("[initLocalCache][缓存文件配置,数量为:{}]", configs.size());
// 第二步:构建缓存创建或更新文件 Client
// 第二步:构建缓存创建或更新文件 Client
configs.forEach(config -> {
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
// 如果是 master进行设置
@@ -114,9 +77,6 @@ public class FileConfigServiceImpl implements FileConfigService {
masterFileClient = fileClientFactory.getFileClient(config.getId());
}
});
// 第三步:设置最新的 maxUpdateTime用于下次的增量判断。
this.maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime);
}
@Override

View File

@@ -28,9 +28,8 @@ import java.time.LocalDateTime;
import java.util.Map;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
@@ -42,10 +41,10 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
/**
* {@link FileConfigServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
* {@link FileConfigServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(FileConfigServiceImpl.class)
public class FileConfigServiceImplTest extends BaseDbUnitTest {
@@ -74,16 +73,13 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient);
// 调用
fileConfigService.initFileClients();
fileConfigService.initLocalCache();
// 断言 fileClientFactory 调用
verify(fileClientFactory).createOrUpdateFileClient(eq(1L),
eq(configDO1.getStorage()), eq(configDO1.getConfig()));
verify(fileClientFactory).createOrUpdateFileClient(eq(2L),
eq(configDO2.getStorage()), eq(configDO2.getConfig()));
assertSame(masterFileClient, fileConfigService.getMasterFileClient());
// 断言 maxUpdateTime 缓存
assertEquals(max(configDO1.getUpdateTime(), configDO2.getUpdateTime()),
fileConfigService.getMaxUpdateTime());
}
@Test
@@ -175,8 +171,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
// 调用
fileConfigService.deleteFileConfig(id);
// 校验数据不存在了
assertNull(fileConfigMapper.selectById(id));
// 校验数据不存在了
assertNull(fileConfigMapper.selectById(id));
// verify 调用
verify(fileConfigProducer).sendFileConfigRefreshMessage();
}
@@ -204,30 +200,30 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
@Test
public void testGetFileConfigPage() {
// mock 数据
FileConfigDO dbFileConfig = randomFileConfigDO().setName("芋道源码")
.setStorage(FileStorageEnum.LOCAL.getStorage());
dbFileConfig.setCreateTime(LocalDateTimeUtil.parse("2020-01-23", DatePattern.NORM_DATE_PATTERN));// 等会查询到
fileConfigMapper.insert(dbFileConfig);
// 测试 name 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setName("源码")));
// 测试 storage 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setStorage(FileStorageEnum.DB.getStorage())));
// 测试 createTime 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setCreateTime(LocalDateTimeUtil.parse("2020-11-23", DatePattern.NORM_DATE_PATTERN))));
// 准备参数
FileConfigPageReqVO reqVO = new FileConfigPageReqVO();
reqVO.setName("芋道");
reqVO.setStorage(FileStorageEnum.LOCAL.getStorage());
reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 1, 1),
buildLocalDateTime(2020, 1, 24)}));
// mock 数据
FileConfigDO dbFileConfig = randomFileConfigDO().setName("芋道源码")
.setStorage(FileStorageEnum.LOCAL.getStorage());
dbFileConfig.setCreateTime(LocalDateTimeUtil.parse("2020-01-23", DatePattern.NORM_DATE_PATTERN));// 等会查询到
fileConfigMapper.insert(dbFileConfig);
// 测试 name 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setName("源码")));
// 测试 storage 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setStorage(FileStorageEnum.DB.getStorage())));
// 测试 createTime 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setCreateTime(LocalDateTimeUtil.parse("2020-11-23", DatePattern.NORM_DATE_PATTERN))));
// 准备参数
FileConfigPageReqVO reqVO = new FileConfigPageReqVO();
reqVO.setName("芋道");
reqVO.setStorage(FileStorageEnum.LOCAL.getStorage());
reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 1, 1),
buildTime(2020, 1, 24)}));
// 调用
PageResult<FileConfigDO> pageResult = fileConfigService.getFileConfigPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbFileConfig, pageResult.getList().get(0));
// 调用
PageResult<FileConfigDO> pageResult = fileConfigService.getFileConfigPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbFileConfig, pageResult.getList().get(0));
}
@Test