From 2a9110ec324d8d53c6482bbbb5c369234f020bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Fri, 11 Sep 2026 16:54:16 +0800 Subject: [PATCH] =?UTF-8?q?perf(=E5=BA=97=E9=93=BA):=20=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0/=E6=94=B9=E5=90=8D=E5=BA=97=E9=93=BA?= =?UTF-8?q?=E5=90=8E=E5=BC=82=E6=AD=A5=E8=A7=A6=E5=8F=91=E4=B8=80=E6=AC=A1?= =?UTF-8?q?=E7=B4=AB=E9=B8=9F=E7=B4=A2=E5=BC=95=E5=88=B7=E6=96=B0=E2=80=94?= =?UTF-8?q?=E2=80=94=E9=98=B2=E6=8A=96=E5=90=88=E5=B9=B62=E5=88=86?= =?UTF-8?q?=E9=92=9F=E7=AA=97=E5=8F=A3+=E5=BB=B6=E8=BF=9F10=E7=A7=92?= =?UTF-8?q?=E7=AD=89=E4=BA=8B=E5=8A=A1=E6=8F=90=E4=BA=A4=EF=BC=8C=E6=8B=BF?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E9=94=81=E6=88=96=E5=A4=B1=E8=B4=A5=E4=B8=8D?= =?UTF-8?q?=E5=BD=B1=E5=93=8D=E6=B7=BB=E5=8A=A0=E6=B5=81=E7=A8=8B=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E7=AD=895=E5=88=86=E9=92=9F=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E8=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shopkey/service/ShopManageService.java | 3 + .../ZiniaoShopIndexRefreshTrigger.java | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ZiniaoShopIndexRefreshTrigger.java diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java index e0d2dbfa..dcbdbffa 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ShopManageService.java @@ -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()); } diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ZiniaoShopIndexRefreshTrigger.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ZiniaoShopIndexRefreshTrigger.java new file mode 100644 index 00000000..59209d21 --- /dev/null +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopkey/service/ZiniaoShopIndexRefreshTrigger.java @@ -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); + } +}