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(自动识别): *
- * // 加锁(自动识别调用方法和参数)
* 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推荐用于需要跨方法/跨服务协调的场景
+ * + * @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