1.48
修改总结 新增文件 SyncLockType.java - 同步锁类型枚举,定义了 JENKINS_SYNC、GITLAB_SYNC、K8S_SYNC 三种锁类型 修改文件 文件 修改内容 SyncLockManager.java 新增 tryLock(SyncLockType, Object...) 和 unlock(SyncLockType, Object...) 方法,支持显式指定锁类型 JenkinsViewServiceImpl.java syncViews 改用 SyncLockType.JENKINS_SYNC JenkinsJobServiceImpl.java syncJobs 两个重载方法都改用 SyncLockType.JENKINS_SYNC,锁粒度统一为 externalSystemId JenkinsBuildServiceImpl.java syncBuilds 改用 SyncLockType.JENKINS_SYNC
This commit is contained in:
parent
c82bb937d1
commit
9f3353e54a
@ -7,13 +7,16 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 智能同步任务本地锁管理器
|
||||
* <p>自动识别调用者(类名+方法名)和参数,生成唯一锁key,无需手动指定锁类型</p>
|
||||
* <p>支持两种使用方式:</p>
|
||||
* <ol>
|
||||
* <li>自动识别调用者(类名+方法名)生成锁key - 适用于单方法独立锁</li>
|
||||
* <li>显式指定锁类型 - 适用于跨方法/跨服务协调锁</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>使用示例:
|
||||
* <p>使用示例1(自动识别):
|
||||
* <pre>
|
||||
* // 加锁(自动识别调用方法和参数)
|
||||
* if (!syncLockManager.tryLock(externalSystemId)) {
|
||||
* return; // 已有同步任务在执行
|
||||
* return;
|
||||
* }
|
||||
* try {
|
||||
* // 执行同步逻辑
|
||||
@ -22,17 +25,91 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>锁key格式:ClassName.methodName:param1:param2:...</p>
|
||||
* <p>使用示例2(显式锁类型 - 推荐用于跨服务协调):
|
||||
* <pre>
|
||||
* if (!syncLockManager.tryLock(SyncLockType.JENKINS_SYNC, externalSystemId)) {
|
||||
* return;
|
||||
* }
|
||||
* try {
|
||||
* // 执行同步逻辑
|
||||
* } finally {
|
||||
* syncLockManager.unlock(SyncLockType.JENKINS_SYNC, externalSystemId);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SyncLockManager {
|
||||
|
||||
// 统一的锁存储:key = ClassName.methodName:param1:param2:...
|
||||
// 统一的锁存储
|
||||
private final ConcurrentHashMap<String, Boolean> locks = new ConcurrentHashMap<>();
|
||||
|
||||
// ==================== 显式锁类型方法(推荐用于跨服务协调) ====================
|
||||
|
||||
/**
|
||||
* 尝试获取锁(显式指定锁类型)
|
||||
* <p>推荐用于需要跨方法/跨服务协调的场景</p>
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
|
||||
// ==================== 自动识别调用者方法(向后兼容) ====================
|
||||
|
||||
/**
|
||||
* 尝试获取锁(自动识别调用者)
|
||||
* <p>适用于单方法独立锁场景,不需要跨服务协调</p>
|
||||
*
|
||||
* @param params 锁参数(如 externalSystemId, viewId等)
|
||||
* @return true-获取成功,false-已被锁定
|
||||
|
||||
@ -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<JenkinsBuild, Jenki
|
||||
@Async
|
||||
@Transactional
|
||||
public void syncBuilds(Long externalSystemId) {
|
||||
// 尝试获取锁(自动识别调用者:JenkinsBuildServiceImpl.syncBuilds)
|
||||
if (!syncLockManager.tryLock(externalSystemId)) {
|
||||
// 尝试获取锁(使用统一的 JENKINS_SYNC 锁类型,与 syncViews、syncJobs 共享锁)
|
||||
if (!syncLockManager.tryLock(SyncLockType.JENKINS_SYNC, externalSystemId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -129,7 +130,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
checkBuildNotifications(externalSystemId);
|
||||
} finally {
|
||||
// 释放锁
|
||||
syncLockManager.unlock(externalSystemId);
|
||||
syncLockManager.unlock(SyncLockType.JENKINS_SYNC, externalSystemId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ import com.qqchen.deploy.backend.deploy.service.IJenkinsSyncHistoryService;
|
||||
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;
|
||||
import com.qqchen.deploy.backend.deploy.lock.SyncLockType;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@ -74,15 +75,15 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
@Async
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncJobs(Long externalSystemId) {
|
||||
// 尝试获取锁(只使用 externalSystemId 作为锁参数)
|
||||
if (!syncLockManager.tryLock(externalSystemId)) {
|
||||
// 尝试获取锁(使用统一的 JENKINS_SYNC 锁类型,与 syncViews、syncBuilds 共享锁)
|
||||
if (!syncLockManager.tryLock(SyncLockType.JENKINS_SYNC, externalSystemId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doSyncJobs(externalSystemId, null);
|
||||
} finally {
|
||||
syncLockManager.unlock(externalSystemId);
|
||||
syncLockManager.unlock(SyncLockType.JENKINS_SYNC, externalSystemId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,15 +97,15 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
@Async
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncJobs(Long externalSystemId, Long viewId) {
|
||||
// 尝试获取锁(使用 externalSystemId 和 viewId 作为锁参数)
|
||||
if (!syncLockManager.tryLock(externalSystemId, viewId)) {
|
||||
// 尝试获取锁(使用统一的 JENKINS_SYNC 锁类型,锁粒度为 externalSystemId,忽略 viewId)
|
||||
if (!syncLockManager.tryLock(SyncLockType.JENKINS_SYNC, externalSystemId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doSyncJobs(externalSystemId, viewId);
|
||||
} finally {
|
||||
syncLockManager.unlock(externalSystemId, viewId);
|
||||
syncLockManager.unlock(SyncLockType.JENKINS_SYNC, externalSystemId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ import com.qqchen.deploy.backend.deploy.service.IJenkinsViewService;
|
||||
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;
|
||||
import com.qqchen.deploy.backend.deploy.lock.SyncLockType;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@ -72,15 +73,15 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
|
||||
@Async
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void syncViews(Long externalSystemId) {
|
||||
// 尝试获取锁
|
||||
if (!syncLockManager.tryLock(externalSystemId)) {
|
||||
// 尝试获取锁(使用统一的 JENKINS_SYNC 锁类型,与 syncJobs、syncBuilds 共享锁)
|
||||
if (!syncLockManager.tryLock(SyncLockType.JENKINS_SYNC, externalSystemId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doSyncViews(externalSystemId);
|
||||
} finally {
|
||||
syncLockManager.unlock(externalSystemId);
|
||||
syncLockManager.unlock(SyncLockType.JENKINS_SYNC, externalSystemId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user