瀏覽代碼

feat(personnel-sync): timer 加整点限流重试 (失败间隔 60s 重试 2 次)

根因: 工作日 08/13/18 整点定时 fullSync 偶发钉钉 subcode=90002 (topapi/v2/department/listsubid 全网整点 QPS >1200)
导致 fetchAllDingUsers 首步抛 McException 中断整轮同步, 下一次 cron 还得再等几小时

修复: runFullSync 加重试循环, 异常不阻断, 等 60s 让钉钉冷却后重试
共 3 次尝试 (首次 + 2 次重试), 仍失败放弃本轮等下一次 cron
MAX_ATTEMPTS=3 / RETRY_DELAY_MS=60_000 常量化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
malk 2 周之前
父節點
當前提交
54fa164a4d
共有 1 個文件被更改,包括 23 次插入4 次删除
  1. 23 4
      mjava-akdsbeisen/src/main/java/com/malk/timer/PersonnelSyncTimer.java

+ 23 - 4
mjava-akdsbeisen/src/main/java/com/malk/timer/PersonnelSyncTimer.java

@@ -25,6 +25,10 @@ public class PersonnelSyncTimer {
     // fixme: 防止上一轮未完成时下一轮重入 (两轮并发会使 QPS 翻倍)
     private final AtomicBoolean running = new AtomicBoolean(false);
 
+    // fixme: 钉钉整点 QPS 高峰偶发 subcode=90002 限流 → 首次失败后再重试 2 次, 间隔 60s 让钉钉冷却; 仍失败放弃等下一次 cron
+    private static final int MAX_ATTEMPTS = 3;
+    private static final long RETRY_DELAY_MS = 60_000L;
+
     /** 工作日 08:00 / 13:00 / 18:00 各一次全量同步(单方法挂 3 条 cron,离散时点无法用单条 cron 表达) */
     @Scheduled(cron = "0 0 8 ? * MON-FRI")
     @Scheduled(cron = "0 0 13 ? * MON-FRI")
@@ -40,10 +44,25 @@ public class PersonnelSyncTimer {
         }
         log.info("[PersonnelSync] 定时同步任务开始 tag={}", tag);
         try {
-            java.util.Map<String, Object> stats = personnelSyncService.fullSync(null);
-            log.info("[PersonnelSync] 定时同步任务完成 tag={} {}", tag, stats);
-        } catch (Exception e) {
-            log.error("[PersonnelSync] 定时同步任务失败 tag={}", tag, e);
+            for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
+                try {
+                    java.util.Map<String, Object> stats = personnelSyncService.fullSync(null);
+                    log.info("[PersonnelSync] 定时同步任务完成 tag={} attempt={}/{} {}", tag, attempt, MAX_ATTEMPTS, stats);
+                    return;
+                } catch (Exception e) {
+                    log.error("[PersonnelSync] 定时同步任务失败 tag={} attempt={}/{}", tag, attempt, MAX_ATTEMPTS, e);
+                    if (attempt < MAX_ATTEMPTS) {
+                        try {
+                            Thread.sleep(RETRY_DELAY_MS);
+                        } catch (InterruptedException ie) {
+                            Thread.currentThread().interrupt();
+                            log.warn("[PersonnelSync] 重试等待被中断,放弃本轮 tag={}", tag);
+                            return;
+                        }
+                    }
+                }
+            }
+            log.error("[PersonnelSync] 定时同步任务连续 {} 次失败,放弃本轮等待下一次 cron 触发 tag={}", MAX_ATTEMPTS, tag);
         } finally {
             running.set(false);
         }