From b54f72d3f6ff5917c93968228f9c3b6d2ed620d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com>
Date: Mon, 14 Sep 2026 17:04:19 +0800
Subject: [PATCH] =?UTF-8?q?fix(=E5=93=81=E7=89=8C=E6=A3=80=E6=B5=8B):=20?=
=?UTF-8?q?=E7=86=94=E6=96=AD=E4=B8=AD=E6=AD=A2=E8=90=BD=E7=9C=9F=E5=AE=9E?=
=?UTF-8?q?=E5=8E=9F=E5=9B=A0+=E9=83=A8=E5=88=86=E7=BB=93=E6=9E=9C?=
=?UTF-8?q?=E5=8F=AF=E4=B8=8B=E8=BD=BD=EF=BC=8C=E7=86=94=E6=96=AD=E5=8A=A0?=
=?UTF-8?q?=E6=8C=81=E7=BB=AD=E6=97=B6=E9=95=BF=E9=97=A8=E6=A7=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 熔断改为「连续失败持续 6 分钟未恢复」才中止:原 8 次即中止,5 线程一轮
就能凑满,重跑机制没机会生效导致任务失败率过高(任务 2309 复盘)
- 期间每 30s 冷却重试,重跑轮次 10→30;限流窗口恢复后任务自动跑完
- 失败终态上报内部接口 /api/internal/brand/tasks/{id}/abort:落真实原因 +
用已收分片部分组装结果(未检测品牌单独成 sheet),不再悬挂到心跳超时被
判「前端长时间无响应」且已跑数据无法下载
- 组装前从分片重建聚合(缓存快照可能缺后加字段如 keptBrands)
- 前端:失败任务有结果文件即显示「下载结果」
---
.../InternalBrandTaskController.java | 56 ++++
.../model/dto/BrandFileAggregateCacheDto.java | 3 +
.../model/dto/BrandTaskAbortRequest.java | 13 +
.../brand/service/BrandTaskService.java | 184 +++++++++++--
.../service/BrandTaskStorageService.java | 8 +
.../service/BrandTaskAbortServiceTest.java | 249 ++++++++++++++++++
.../pages/brand/components/BrandBrandTab.vue | 5 +-
7 files changed, 500 insertions(+), 18 deletions(-)
create mode 100644 backend-java/src/main/java/com/nanri/aiimage/modules/brand/controller/InternalBrandTaskController.java
create mode 100644 backend-java/src/main/java/com/nanri/aiimage/modules/brand/model/dto/BrandTaskAbortRequest.java
create mode 100644 backend-java/src/test/java/com/nanri/aiimage/modules/brand/service/BrandTaskAbortServiceTest.java
diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/brand/controller/InternalBrandTaskController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/brand/controller/InternalBrandTaskController.java
new file mode 100644
index 00000000..152b52bd
--- /dev/null
+++ b/backend-java/src/main/java/com/nanri/aiimage/modules/brand/controller/InternalBrandTaskController.java
@@ -0,0 +1,56 @@
+package com.nanri.aiimage.modules.brand.controller;
+
+import com.nanri.aiimage.common.api.ApiResponse;
+import com.nanri.aiimage.common.exception.BusinessException;
+import com.nanri.aiimage.common.security.AdminAuthSupport;
+import com.nanri.aiimage.modules.brand.model.dto.BrandTaskAbortRequest;
+import com.nanri.aiimage.modules.brand.service.BrandTaskService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * 内部接口:品牌任务中止上报,供主机 A 品牌检测服务(15126)在爬取不可继续时调用
+ * (如 WIPO 连续限流熔断)。Java 侧用已收到的结果分片部分组装结果文件并落 failed +
+ * 真实原因,避免任务悬挂到心跳超时被判「前端长时间无响应」、已跑出的数据无法下载。
+ *
+ *
鉴权:仅凭 X-Internal-Token(与容器 AIIMAGE_INTERNAL_TOKEN / 宿主机
+ * ~/.aiimage/internal-token 同值)。/api/internal 前缀虽在 AdminApiGuardFilter 兜底
+ * 名单内、可信令牌会放行,controller 仍须自校验——防止配置漂移时匿名可达。
+ */
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+@RequestMapping("/api/internal/brand")
+@Tag(name = "内部接口", description = "服务间调用(X-Internal-Token 鉴权)。")
+public class InternalBrandTaskController {
+
+ private final BrandTaskService brandTaskService;
+ private final AdminAuthSupport adminAuthSupport;
+
+ @PostMapping("/tasks/{taskId}/abort")
+ @Operation(summary = "上报品牌任务中止(爬取方调用)",
+ description = "用已收到的结果分片部分组装结果文件(未检测品牌单独成 sheet)并落 failed + 真实原因;幂等,终态任务直接返回。")
+ public ApiResponse