perf(店铺): 后台添加/改名店铺后异步触发一次紫鸟索引刷新——防抖合并2分钟窗口+延迟10秒等事务提交,拿不到锁或失败不影响添加流程,不等5分钟定时轮
This commit is contained in:
+3
@@ -26,6 +26,7 @@ public class ShopManageService {
|
|||||||
private final ShopManageMapper shopManageMapper;
|
private final ShopManageMapper shopManageMapper;
|
||||||
private final ShopManageGroupService shopManageGroupService;
|
private final ShopManageGroupService shopManageGroupService;
|
||||||
private final ShopCredentialCryptoService shopCredentialCryptoService;
|
private final ShopCredentialCryptoService shopCredentialCryptoService;
|
||||||
|
private final ZiniaoShopIndexRefreshTrigger ziniaoShopIndexRefreshTrigger;
|
||||||
|
|
||||||
public ShopManagePageVo page(long page, long pageSize, Long groupId, String shopName, Long operatorId, boolean superAdmin) {
|
public ShopManagePageVo page(long page, long pageSize, Long groupId, String shopName, Long operatorId, boolean superAdmin) {
|
||||||
long safePage = Math.max(page, 1);
|
long safePage = Math.max(page, 1);
|
||||||
@@ -98,6 +99,7 @@ public class ShopManageService {
|
|||||||
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
||||||
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
||||||
shopManageMapper.insert(entity);
|
shopManageMapper.insert(entity);
|
||||||
|
ziniaoShopIndexRefreshTrigger.trigger("create:" + entity.getShopName());
|
||||||
ShopManageEntity saved = getById(entity.getId());
|
ShopManageEntity saved = getById(entity.getId());
|
||||||
return toItemVo(saved, group.getGroupName());
|
return toItemVo(saved, group.getGroupName());
|
||||||
}
|
}
|
||||||
@@ -121,6 +123,7 @@ public class ShopManageService {
|
|||||||
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
||||||
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
||||||
shopManageMapper.updateById(entity);
|
shopManageMapper.updateById(entity);
|
||||||
|
ziniaoShopIndexRefreshTrigger.trigger("update:" + entity.getShopName());
|
||||||
ShopManageEntity updated = getById(id);
|
ShopManageEntity updated = getById(id);
|
||||||
return toItemVo(updated, group.getGroupName());
|
return toItemVo(updated, group.getGroupName());
|
||||||
}
|
}
|
||||||
|
|||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package com.nanri.aiimage.modules.shopkey.service;
|
||||||
|
|
||||||
|
import com.nanri.aiimage.modules.ziniao.service.ZiniaoShopIndexRefreshService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台店铺添加/改名后异步触发一次紫鸟店铺索引刷新。
|
||||||
|
* 调用方不阻塞;带防抖(合并窗口内的多次触发);拿不到分布式锁或刷新失败不影响添加流程。
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class ZiniaoShopIndexRefreshTrigger {
|
||||||
|
|
||||||
|
/** 防抖:触发后 N 分钟内的重复触发合并掉(刷新一轮本身要几十秒)。 */
|
||||||
|
private static final long DEBOUNCE_MILLIS = Duration.ofMinutes(2).toMillis();
|
||||||
|
|
||||||
|
private final ZiniaoShopIndexRefreshService ziniaoShopIndexRefreshService;
|
||||||
|
private final AtomicLong lastTriggerAtMillis = new AtomicLong(0);
|
||||||
|
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(runnable -> {
|
||||||
|
Thread thread = new Thread(runnable, "ziniao-index-refresh-trigger");
|
||||||
|
thread.setDaemon(true);
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
|
|
||||||
|
public ZiniaoShopIndexRefreshTrigger(ZiniaoShopIndexRefreshService ziniaoShopIndexRefreshService) {
|
||||||
|
this.ziniaoShopIndexRefreshService = ziniaoShopIndexRefreshService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trigger(String source) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long last = lastTriggerAtMillis.get();
|
||||||
|
if (now - last < DEBOUNCE_MILLIS && !lastTriggerAtMillis.compareAndSet(last, now)) {
|
||||||
|
log.info("[ziniao-index] 触发防抖合并 source={} 距上次触发不足2分钟", source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastTriggerAtMillis.set(now);
|
||||||
|
// 延迟 10 秒:等添加事务提交 & 躲开定时轮刚启动的瞬间
|
||||||
|
executor.schedule(() -> {
|
||||||
|
try {
|
||||||
|
ziniaoShopIndexRefreshService.refreshShopIndexManually();
|
||||||
|
log.info("[ziniao-index] 店铺变动后增量刷新完成 source={}", source);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.info("[ziniao-index] 店铺变动后触发刷新未执行(可能有定时轮在刷新),source={} msg={}",
|
||||||
|
source, ex.getMessage());
|
||||||
|
}
|
||||||
|
}, 10, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user