mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-25 08:25:07 +08:00
优化本地缓存的刷新实现,数据变更时,强制刷新
This commit is contained in:
@ -22,7 +22,7 @@ public interface PayChannelService {
|
||||
/**
|
||||
* 初始化支付客户端
|
||||
*/
|
||||
void initPayClients();
|
||||
void initLocalCache();
|
||||
|
||||
/**
|
||||
* 创建支付渠道
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.pay.service.merchant;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
@ -10,7 +9,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelCreateReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO;
|
||||
@ -20,7 +19,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper;
|
||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -66,53 +64,47 @@ public class PayChannelServiceImpl implements PayChannelService {
|
||||
@Resource
|
||||
private Validator validator;
|
||||
|
||||
@Resource
|
||||
@Lazy // 注入自己,所以延迟加载
|
||||
private PayChannelService self;
|
||||
|
||||
/**
|
||||
* 初始化 {@link #payClientFactory} 缓存
|
||||
*/
|
||||
@Override
|
||||
@PostConstruct
|
||||
@TenantIgnore // 忽略自动化租户,全局初始化本地缓存
|
||||
public void initPayClients() {
|
||||
// 获取支付渠道,如果有更新
|
||||
List<PayChannelDO> payChannels = loadPayChannelIfUpdate(maxUpdateTime);
|
||||
if (CollUtil.isEmpty(payChannels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建或更新支付 Client
|
||||
payChannels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),
|
||||
payChannel.getCode(), payChannel.getConfig()));
|
||||
|
||||
// 写入缓存
|
||||
maxUpdateTime = CollectionUtils.getMaxValue(payChannels, PayChannelDO::getUpdateTime);
|
||||
log.info("[initPayClients][初始化 PayChannel 数量为 {}]", payChannels.size());
|
||||
public void initLocalCache() {
|
||||
initLocalCacheIfUpdate(null);
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
||||
public void schedulePeriodicRefresh() {
|
||||
self.initPayClients();
|
||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果支付渠道发生变化,从数据库中获取最新的全量支付渠道。
|
||||
* 如果未发生变化,则返回空
|
||||
* 刷新本地缓存
|
||||
*
|
||||
* @param maxUpdateTime 当前支付渠道的最大更新时间
|
||||
* @return 支付渠道列表
|
||||
* @param maxUpdateTime 最大更新时间
|
||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
||||
*/
|
||||
private List<PayChannelDO> loadPayChannelIfUpdate(LocalDateTime maxUpdateTime) {
|
||||
// 第一步,判断是否要更新。
|
||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||
log.info("[loadPayChannelIfUpdate][首次加载全量支付渠道]");
|
||||
} else { // 判断数据库中是否有更新的支付渠道
|
||||
if (channelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
return null;
|
||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
||||
// 注意:忽略自动多租户,因为要全局初始化缓存
|
||||
TenantUtils.executeIgnore(() -> {
|
||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
||||
if (maxUpdateTime != null
|
||||
&& channelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
||||
return;
|
||||
}
|
||||
log.info("[loadPayChannelIfUpdate][增量加载全量支付渠道]");
|
||||
}
|
||||
// 第二步,如果有更新,则从数据库加载所有支付渠道
|
||||
return channelMapper.selectList();
|
||||
List<PayChannelDO> channels = channelMapper.selectList();
|
||||
log.info("[initLocalCacheIfUpdate][缓存支付渠道,数量为:{}]", channels.size());
|
||||
|
||||
// 第二步:构建缓存。创建或更新支付 Client
|
||||
channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),
|
||||
payChannel.getCode(), payChannel.getConfig()));
|
||||
|
||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
||||
this.maxUpdateTime = CollectionUtils.getMaxValue(channels, PayChannelDO::getUpdateTime);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,7 +49,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
|
||||
@Test
|
||||
public void testCreateWechatVersion2Channel_success() {
|
||||
// 准备参数
|
||||
|
||||
WXPayClientConfig v2Config = getV2Config();
|
||||
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
|
||||
o.setCode(PayChannelEnum.WX_PUB.getCode());
|
||||
|
@ -43,6 +43,7 @@ CREATE TABLE IF NOT EXISTS "pay_channel" (
|
||||
"updater" varchar(64) NULL DEFAULT '',
|
||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
"deleted" bit(1) NOT NULL DEFAULT FALSE,
|
||||
"tenant_id" bigint not null default '0',
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT = '支付渠道';
|
||||
|
||||
|
Reference in New Issue
Block a user