perf(店铺): 后台添加/改名店铺后异步触发一次紫鸟索引刷新——防抖合并2分钟窗口+延迟10秒等事务提交,拿不到锁或失败不影响添加流程,不等5分钟定时轮
This commit is contained in:
+3
@@ -26,6 +26,7 @@ public class ShopManageService {
|
||||
private final ShopManageMapper shopManageMapper;
|
||||
private final ShopManageGroupService shopManageGroupService;
|
||||
private final ShopCredentialCryptoService shopCredentialCryptoService;
|
||||
private final ZiniaoShopIndexRefreshTrigger ziniaoShopIndexRefreshTrigger;
|
||||
|
||||
public ShopManagePageVo page(long page, long pageSize, Long groupId, String shopName, Long operatorId, boolean superAdmin) {
|
||||
long safePage = Math.max(page, 1);
|
||||
@@ -98,6 +99,7 @@ public class ShopManageService {
|
||||
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
||||
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
||||
shopManageMapper.insert(entity);
|
||||
ziniaoShopIndexRefreshTrigger.trigger("create:" + entity.getShopName());
|
||||
ShopManageEntity saved = getById(entity.getId());
|
||||
return toItemVo(saved, group.getGroupName());
|
||||
}
|
||||
@@ -121,6 +123,7 @@ public class ShopManageService {
|
||||
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
||||
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
||||
shopManageMapper.updateById(entity);
|
||||
ziniaoShopIndexRefreshTrigger.trigger("update:" + entity.getShopName());
|
||||
ShopManageEntity updated = getById(id);
|
||||
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