From 9f3353e54acd335eafad8500001fe0b39d9d9fc3 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Wed, 31 Dec 2025 10:42:10 +0800 Subject: [PATCH] =?UTF-8?q?1.48=20=E4=BF=AE=E6=94=B9=E6=80=BB=E7=BB=93=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=87=E4=BB=B6=20SyncLockType.java=20-=20?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E9=94=81=E7=B1=BB=E5=9E=8B=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=EF=BC=8C=E5=AE=9A=E4=B9=89=E4=BA=86=20JENKINS=5FSYNC=E3=80=81G?= =?UTF-8?q?ITLAB=5FSYNC=E3=80=81K8S=5FSYNC=20=E4=B8=89=E7=A7=8D=E9=94=81?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=20=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?=E6=96=87=E4=BB=B6=09=E4=BF=AE=E6=94=B9=E5=86=85=E5=AE=B9=20Syn?= =?UTF-8?q?cLockManager.java=09=E6=96=B0=E5=A2=9E=20tryLock(SyncLockType,?= =?UTF-8?q?=20Object...)=20=E5=92=8C=20unlock(SyncLockType,=20Object...)?= =?UTF-8?q?=20=E6=96=B9=E6=B3=95=EF=BC=8C=E6=94=AF=E6=8C=81=E6=98=BE?= =?UTF-8?q?=E5=BC=8F=E6=8C=87=E5=AE=9A=E9=94=81=E7=B1=BB=E5=9E=8B=20Jenkin?= =?UTF-8?q?sViewServiceImpl.java=09syncViews=20=E6=94=B9=E7=94=A8=20SyncLo?= =?UTF-8?q?ckType.JENKINS=5FSYNC=20JenkinsJobServiceImpl.java=09syncJobs?= =?UTF-8?q?=20=E4=B8=A4=E4=B8=AA=E9=87=8D=E8=BD=BD=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E9=83=BD=E6=94=B9=E7=94=A8=20SyncLockType.JENKINS=5FSYNC?= =?UTF-8?q?=EF=BC=8C=E9=94=81=E7=B2=92=E5=BA=A6=E7=BB=9F=E4=B8=80=E4=B8=BA?= =?UTF-8?q?=20externalSystemId=20JenkinsBuildServiceImpl.java=09syncBuilds?= =?UTF-8?q?=20=E6=94=B9=E7=94=A8=20SyncLockType.JENKINS=5FSYNC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/deploy/lock/SyncLockManager.java | 89 +++++++++++++++++-- .../service/impl/JenkinsBuildServiceImpl.java | 7 +- .../service/impl/JenkinsJobServiceImpl.java | 13 +-- .../service/impl/JenkinsViewServiceImpl.java | 7 +- 4 files changed, 98 insertions(+), 18 deletions(-) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/lock/SyncLockManager.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/lock/SyncLockManager.java index 87a3553e..14060780 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/lock/SyncLockManager.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/lock/SyncLockManager.java @@ -7,13 +7,16 @@ import java.util.concurrent.ConcurrentHashMap; /** * 智能同步任务本地锁管理器 - *

自动识别调用者(类名+方法名)和参数,生成唯一锁key,无需手动指定锁类型

+ *

支持两种使用方式:

+ *
    + *
  1. 自动识别调用者(类名+方法名)生成锁key - 适用于单方法独立锁
  2. + *
  3. 显式指定锁类型 - 适用于跨方法/跨服务协调锁
  4. + *
* - *

使用示例: + *

使用示例1(自动识别): *

- * // 加锁(自动识别调用方法和参数)
  * if (!syncLockManager.tryLock(externalSystemId)) {
- *     return; // 已有同步任务在执行
+ *     return;
  * }
  * try {
  *     // 执行同步逻辑
@@ -22,17 +25,91 @@ import java.util.concurrent.ConcurrentHashMap;
  * }
  * 
* - *

锁key格式:ClassName.methodName:param1:param2:...

+ *

使用示例2(显式锁类型 - 推荐用于跨服务协调): + *

+ * if (!syncLockManager.tryLock(SyncLockType.JENKINS_SYNC, externalSystemId)) {
+ *     return;
+ * }
+ * try {
+ *     // 执行同步逻辑
+ * } finally {
+ *     syncLockManager.unlock(SyncLockType.JENKINS_SYNC, externalSystemId);
+ * }
+ * 
*/ @Slf4j @Component public class SyncLockManager { - // 统一的锁存储:key = ClassName.methodName:param1:param2:... + // 统一的锁存储 private final ConcurrentHashMap locks = new ConcurrentHashMap<>(); + // ==================== 显式锁类型方法(推荐用于跨服务协调) ==================== + + /** + * 尝试获取锁(显式指定锁类型) + *

推荐用于需要跨方法/跨服务协调的场景

+ * + * @param lockType 锁类型 + * @param params 锁参数(如 externalSystemId) + * @return true-获取成功,false-已被锁定 + */ + public boolean tryLock(SyncLockType lockType, Object... params) { + String lockKey = buildLockKey(lockType, params); + boolean acquired = locks.putIfAbsent(lockKey, true) == null; + + if (!acquired) { + log.warn("同步任务正在执行中,跳过本次同步: lockType={}, params={}", + lockType.getKey(), formatParams(params)); + } else { + log.debug("获取同步锁成功: lockType={}, params={}", + lockType.getKey(), formatParams(params)); + } + + return acquired; + } + + /** + * 释放锁(显式指定锁类型) + * + * @param lockType 锁类型 + * @param params 锁参数(必须与tryLock时完全一致) + */ + public void unlock(SyncLockType lockType, Object... params) { + String lockKey = buildLockKey(lockType, params); + locks.remove(lockKey); + log.debug("同步任务完成,释放锁: lockType={}, params={}", + lockType.getKey(), formatParams(params)); + } + + /** + * 检查锁是否被持有(显式指定锁类型) + * + * @param lockType 锁类型 + * @param params 锁参数 + * @return true-已被锁定,false-未锁定 + */ + public boolean isLocked(SyncLockType lockType, Object... params) { + String lockKey = buildLockKey(lockType, params); + return locks.containsKey(lockKey); + } + + /** + * 构建锁key(显式锁类型) + */ + private String buildLockKey(SyncLockType lockType, Object... params) { + StringBuilder key = new StringBuilder(lockType.getKey()); + for (Object param : params) { + key.append(":").append(param != null ? param : "null"); + } + return key.toString(); + } + + // ==================== 自动识别调用者方法(向后兼容) ==================== + /** * 尝试获取锁(自动识别调用者) + *

适用于单方法独立锁场景,不需要跨服务协调

* * @param params 锁参数(如 externalSystemId, viewId等) * @return true-获取成功,false-已被锁定 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java index 4ac11a5c..a9c418a5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java @@ -25,6 +25,7 @@ import com.qqchen.deploy.backend.notification.service.INotificationSendService; import com.qqchen.deploy.backend.notification.dto.SendNotificationRequest; import com.qqchen.deploy.backend.deploy.dto.sync.JenkinsSyncContext; import com.qqchen.deploy.backend.deploy.lock.SyncLockManager; +import com.qqchen.deploy.backend.deploy.lock.SyncLockType; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; @@ -117,8 +118,8 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl