瀏覽代碼

feat(workflow): 添加任务超时自动失败和退款功能

- 将Docker API版本从1.44降级到1.43以确保兼容性
- 新增handleTimeout方法处理超时订单的退款和相册失败标记
- 实现定时任务每10分钟检测并自动处理超过20分钟的执行中任务
- 添加日志记录以追踪超时任务的处理状态和结果
ChenYu 7 月之前
父節點
當前提交
19961f5518

+ 36 - 0
src/main/java/com/aitori/scheduler/WorkflowTaskScheduler.java

@@ -72,4 +72,40 @@ public class WorkflowTaskScheduler {
         log.info("轮询超时任务完成: 总数={}, 已处理={}, 仍执行中={}, 异常={}",
                 pendingOrders.size(), processed, stillRunning, failed);
     }
+
+    /**
+     * 每10分钟检测一次:将创建时间超过20分钟且仍处于"执行中"的任务标记为超时失败,
+     * 自动退款并标记相册失败。
+     */
+    @Scheduled(fixedRate = 10 * 60 * 1000, initialDelay = 2 * 60 * 1000)
+    @SchedulerLock(name = "autoFailTimeoutTasks", lockAtMostFor = "PT10M", lockAtLeastFor = "PT1M")
+    public void autoFailTimeoutTasks() {
+        LocalDateTime timeoutThreshold = LocalDateTime.now().minusMinutes(20);
+        List<TAiOrderV2> timeoutOrders = aiOrderV2Service.list(
+                new LambdaQueryWrapper<TAiOrderV2>()
+                        .eq(TAiOrderV2::getTaskStatus, 1)
+                        .le(TAiOrderV2::getCreateTime, timeoutThreshold)
+        );
+
+        if (timeoutOrders.isEmpty()) {
+            log.debug("无超时需自动失败的任务");
+            return;
+        }
+
+        log.info("开始处理超时任务自动失败, 共{}条", timeoutOrders.size());
+        int success = 0;
+        int failed = 0;
+
+        for (TAiOrderV2 order : timeoutOrders) {
+            try {
+                resultHandler.handleTimeout(order, "任务执行超时(超过20分钟),系统自动标记失败");
+                success++;
+            } catch (Exception e) {
+                failed++;
+                log.error("超时任务自动失败处理异常, orderId={}, taskId={}", order.getId(), order.getTaskId(), e);
+            }
+        }
+
+        log.info("超时任务自动失败处理完成: 总数={}, 成功={}, 异常={}", timeoutOrders.size(), success, failed);
+    }
 }

+ 1 - 1
src/main/java/com/aitori/service/DockerLogService.java

@@ -44,7 +44,7 @@ public class DockerLogService {
         }
 
         String requestPath = String.format(
-                "/v1.44/containers/%s/logs?stdout=true&stderr=true&tail=%d&timestamps=true",
+                "/v1.43/containers/%s/logs?stdout=true&stderr=true&tail=%d&timestamps=true",
                 containerName, tailLines);
 
         byte[] rawResponse = callDockerApi(sockFile, requestPath);

+ 13 - 0
src/main/java/com/aitori/service/WorkflowTaskResultHandler.java

@@ -201,6 +201,19 @@ public class WorkflowTaskResultHandler {
         return album;
     }
 
+    /**
+     * 处理超时任务:退款并标记相册失败
+     */
+    public void handleTimeout(TAiOrderV2 order, String timeoutMessage) {
+        if (order.getTaskStatus() != null && (order.getTaskStatus() == 2 || order.getTaskStatus() == 3)) {
+            log.info("订单已处理, orderId={}, taskStatus={}, 跳过超时处理", order.getId(), order.getTaskStatus());
+            return;
+        }
+        aiOrderV2Service.refundOrder(order, timeoutMessage);
+        failAlbumIfExists(order.getId());
+        log.info("超时任务已自动失败并退款, orderId={}, taskId={}", order.getId(), order.getTaskId());
+    }
+
     private void failAlbumIfExists(String orderId) {
         if (orderId == null) {
             return;