增加构建通知

This commit is contained in:
dengqichen 2025-12-01 17:54:29 +08:00
parent 433887c3cf
commit 35fb294879
2 changed files with 60 additions and 76 deletions

View File

@ -29,6 +29,7 @@ import com.qqchen.deploy.backend.notification.dto.WeworkSendNotificationRequest;
import com.qqchen.deploy.backend.notification.dto.EmailSendNotificationRequest; import com.qqchen.deploy.backend.notification.dto.EmailSendNotificationRequest;
import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum; import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum;
import com.qqchen.deploy.backend.deploy.dto.sync.JenkinsSyncContext; import com.qqchen.deploy.backend.deploy.dto.sync.JenkinsSyncContext;
import com.qqchen.deploy.backend.deploy.lock.SyncLockManager;
import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
@ -108,18 +109,30 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
@Resource @Resource
private INotificationService notificationService; private INotificationService notificationService;
@Resource(name = "jenkinsTaskExecutor") @Resource(name = "jenkinsTaskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor; private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Resource
private SyncLockManager syncLockManager;
@Override @Override
@Async @Async
@Transactional @Transactional
public void syncBuilds(Long externalSystemId) { public void syncBuilds(Long externalSystemId) {
// 尝试获取锁自动识别调用者JenkinsBuildServiceImpl.syncBuilds
if (!syncLockManager.tryLock(externalSystemId)) {
return;
}
try {
doSyncBuilds(externalSystemId, null, null); doSyncBuilds(externalSystemId, null, null);
// 同步完成后检查并发送构建通知 // 同步完成后检查并发送构建通知
checkBuildNotifications(externalSystemId); checkBuildNotifications(externalSystemId);
} finally {
// 释放锁
syncLockManager.unlock(externalSystemId);
}
} }
private JenkinsSyncContext createSyncContext(Long externalSystemId) { private JenkinsSyncContext createSyncContext(Long externalSystemId) {
@ -220,24 +233,39 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
return 0; return 0;
} }
// 1. 获取数据库中最后一次构建记录 Integer latestBuildNumber = jobResponse.getLastBuild().getNumber();
Optional<JenkinsBuild> lastBuild = jenkinsBuildRepository.findTopByExternalSystemIdAndJobIdOrderByBuildNumberDesc( Integer lastSyncedBuildNumber = job.getLastBuildNumber();
externalSystem.getId(), job.getId());
// 2. 获取需要同步的构建信息 // 1. 判断是否有新构建对比本地缓存的 lastBuildNumber Jenkins 最新的
List<JenkinsBuildResponse> newBuilds = getNewBuilds(externalSystem, job, jobResponse, lastBuild); if (lastSyncedBuildNumber != null && latestBuildNumber <= lastSyncedBuildNumber) {
if (newBuilds.isEmpty()) { log.info("No new builds to sync for job: {} (last synced: {}, latest: {})", job.getJobName(), lastSyncedBuildNumber, latestBuildNumber);
log.info("No new builds to sync for job: {}", job.getJobName());
return 0; return 0;
} }
// 3. 保存新的构建信息 // 2. 确定同步范围
Integer fromBuildNumber = (lastSyncedBuildNumber != null) ? lastSyncedBuildNumber + 1 : 1;
// 3. 获取构建信息
List<JenkinsBuildResponse> builds = jenkinsServiceIntegration.listBuilds(externalSystem, job.getJobName());
// 4. 过滤出需要同步的构建
List<JenkinsBuildResponse> newBuilds = builds.stream()
.filter(build -> build.getNumber() >= fromBuildNumber && build.getNumber() <= latestBuildNumber)
.collect(Collectors.toList());
if (newBuilds.isEmpty()) {
log.info("No new builds found for job: {} (from: {}, to: {})", job.getJobName(), fromBuildNumber, latestBuildNumber);
return 0;
}
// 5. 保存新的构建信息
saveNewBuilds(externalSystem, job, newBuilds); saveNewBuilds(externalSystem, job, newBuilds);
// 4. 更新任务的最新构建信息 // 6. 更新任务的最新构建信息
updateJobLastBuild(job, jobResponse); updateJobLastBuild(job, jobResponse);
log.info("Successfully synchronized {} builds for job: {}", newBuilds.size(), job.getJobName()); log.info("Successfully synchronized {} builds for job: {} (from: {}, to: {})",
newBuilds.size(), job.getJobName(), fromBuildNumber, latestBuildNumber);
return newBuilds.size(); return newBuilds.size();
} catch (Exception e) { } catch (Exception e) {
log.error("Failed to sync job: {}", job.getJobName(), e); log.error("Failed to sync job: {}", job.getJobName(), e);
@ -245,50 +273,6 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
} }
} }
private List<JenkinsBuildResponse> getNewBuilds(
ExternalSystem externalSystem,
JenkinsJob job,
JenkinsJobResponse jobResponse,
Optional<JenkinsBuild> lastBuild) {
// 1. 获取最新构建号从jobResponse中获取避免额外的API调用
if (jobResponse.getLastBuild() == null) {
log.info("No builds found for job: {}", job.getJobName());
return Collections.emptyList();
}
Integer latestBuildNumber = jobResponse.getLastBuild().getNumber();
// 2. 确定同步范围
Integer fromBuildNumber;
if (lastBuild.isEmpty()) {
// 首次同步从第一个构建开始
log.info("First time sync for job: {}, will sync all builds", job.getJobName());
fromBuildNumber = 1;
} else {
// 增量同步从上次同步的下一个构建开始
fromBuildNumber = lastBuild.get().getBuildNumber() + 1;
}
// 3. 如果没有新的构建直接返回
if (fromBuildNumber > latestBuildNumber) {
log.info("No new builds to sync for job: {} (last build: {}, latest build: {})",
job.getJobName(), lastBuild.map(JenkinsBuild::getBuildNumber).orElse(null), latestBuildNumber);
return Collections.emptyList();
}
// 4. 获取构建信息
List<JenkinsBuildResponse> builds = jenkinsServiceIntegration.listBuilds(externalSystem, job.getJobName());
// 5. 过滤出需要的构建
List<JenkinsBuildResponse> newBuilds = builds.stream()
.filter(build -> build.getNumber() >= fromBuildNumber && build.getNumber() <= latestBuildNumber)
.collect(Collectors.toList());
log.info("Found {} new builds for job: {} (from build: {}, to build: {})",
newBuilds.size(), job.getJobName(), fromBuildNumber, latestBuildNumber);
return newBuilds;
}
private void saveNewBuilds( private void saveNewBuilds(
ExternalSystem externalSystem, ExternalSystem externalSystem,
JenkinsJob job, JenkinsJob job,

View File

@ -53,8 +53,8 @@ public class JenkinsSyncHistoryServiceImpl extends BaseServiceImpl<JenkinsSyncHi
/** /**
* 生成同步历史编号 * 生成同步历史编号
* 格式{同步类型}_{年月日时分秒}_{系统ID} * 格式{同步类型}_{年月日时分秒毫秒}_{系统ID}
* 例如VIEW_20231220123456_1 * 例如VIEW_20231220123456789_1
* *
* @param syncType 同步类型 * @param syncType 同步类型
* @param externalSystemId 外部系统ID * @param externalSystemId 外部系统ID
@ -63,7 +63,7 @@ public class JenkinsSyncHistoryServiceImpl extends BaseServiceImpl<JenkinsSyncHi
private String generateSyncHistoryNumber(JenkinsSyncType syncType, Long externalSystemId) { private String generateSyncHistoryNumber(JenkinsSyncType syncType, Long externalSystemId) {
return String.format("%s_%s_%d", return String.format("%s_%s_%d",
syncType.name(), syncType.name(),
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")),
externalSystemId); externalSystemId);
} }
} }