增加动态定时器

This commit is contained in:
dengqichen 2025-10-29 20:56:20 +08:00
parent 3ad79299c3
commit a265275b97
19 changed files with 475 additions and 270 deletions

View File

@ -54,6 +54,22 @@ public class ExternalSystemApiController extends BaseController<ExternalSystem,
return Response.success();
}
@Operation(summary = "获取Jenkins实例信息")
@GetMapping("/{id}/jenkins-instance")
public Response<com.qqchen.deploy.backend.deploy.dto.JenkinsInstanceDTO> getJenkinsInstance(
@Parameter(description = "外部系统ID", required = true) @PathVariable Long id
) {
return Response.success(externalSystemService.getJenkinsInstance(id));
}
@Operation(summary = "获取Git实例信息")
@GetMapping("/{id}/git-instance")
public Response<com.qqchen.deploy.backend.deploy.dto.GitInstanceDTO> getGitInstance(
@Parameter(description = "外部系统ID", required = true) @PathVariable Long id
) {
return Response.success(externalSystemService.getGitInstance(id));
}
@Override
protected void exportData(HttpServletResponse response, List<ExternalSystemDTO> data) {
// TODO: 实现导出功能

View File

@ -1,13 +1,17 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.deploy.entity.JenkinsBuild;
import com.qqchen.deploy.backend.deploy.dto.JenkinsBuildDTO;
import com.qqchen.deploy.backend.deploy.query.JenkinsBuildQuery;
import com.qqchen.deploy.backend.deploy.service.IJenkinsBuildService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@ -20,6 +24,29 @@ import java.util.List;
@Tag(name = "Jenkins构建信息管理", description = "Jenkins构建信息管理相关接口")
public class JenkinsBuildApiController extends BaseController<JenkinsBuild, JenkinsBuildDTO, Long, JenkinsBuildQuery> {
@Resource
private IJenkinsBuildService jenkinsBuildService;
@Operation(summary = "同步Jenkins构建", description = "异步同步支持三种模式1)只传externalSystemId-全量同步 2)传externalSystemId+viewId-同步视图 3)传externalSystemId+viewId+jobId-同步单个任务")
@PostMapping("/sync")
public Response<Void> sync(
@Parameter(description = "外部系统ID", required = true) @RequestParam Long externalSystemId,
@Parameter(description = "视图ID可选", required = false) @RequestParam(required = false) Long viewId,
@Parameter(description = "任务ID可选传此参数时viewId必传", required = false) @RequestParam(required = false) Long jobId
) {
if (jobId != null) {
// 同步单个任务
jenkinsBuildService.syncBuilds(externalSystemId, viewId, jobId);
} else if (viewId != null) {
// 同步视图
jenkinsBuildService.syncBuilds(externalSystemId, viewId);
} else {
// 全量同步
jenkinsBuildService.syncBuilds(externalSystemId);
}
return Response.success();
}
@Override
protected void exportData(HttpServletResponse response, List<JenkinsBuildDTO> data) {
// TODO: 实现导出逻辑

View File

@ -1,13 +1,17 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
import com.qqchen.deploy.backend.deploy.dto.JenkinsJobDTO;
import com.qqchen.deploy.backend.deploy.query.JenkinsJobQuery;
import com.qqchen.deploy.backend.deploy.service.IJenkinsJobService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@ -20,6 +24,25 @@ import java.util.List;
@Tag(name = "Jenkins工作管理", description = "Jenkins工作管理相关接口")
public class JenkinsJobApiController extends BaseController<JenkinsJob, JenkinsJobDTO, Long, JenkinsJobQuery> {
@Resource
private IJenkinsJobService jenkinsJobService;
@Operation(summary = "同步Jenkins任务", description = "异步同步支持两种模式1)只传externalSystemId-全量同步 2)传externalSystemId+viewId-同步指定视图")
@PostMapping("/sync")
public Response<Void> sync(
@Parameter(description = "外部系统ID", required = true) @RequestParam Long externalSystemId,
@Parameter(description = "视图ID可选", required = false) @RequestParam(required = false) Long viewId
) {
if (viewId != null) {
// 同步指定视图
jenkinsJobService.syncJobs(externalSystemId, viewId);
} else {
// 全量同步
jenkinsJobService.syncJobs(externalSystemId);
}
return Response.success();
}
@Override
protected void exportData(HttpServletResponse response, List<JenkinsJobDTO> data) {
// TODO: 实现导出逻辑

View File

@ -1,66 +0,0 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.deploy.dto.JenkinsInstanceDTO;
import com.qqchen.deploy.backend.deploy.service.IJenkinsManagerService;
import com.qqchen.deploy.backend.framework.api.Response;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* Jenkins管理API控制器
*/
@Slf4j
@RestController
@RequestMapping("/api/v1/jenkins-manager")
@Tag(name = "Jenkins管理", description = "Jenkins管理相关接口")
public class JenkinsManagerApiController {
@Resource
private IJenkinsManagerService jenkinsManagerService;
@Operation(summary = "同步所有Jenkins数据")
@PostMapping("/{externalSystemId}/sync-all")
public Response<Void> syncAll(
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
) {
jenkinsManagerService.syncAll(externalSystemId);
return Response.success();
}
@Operation(summary = "同步Jenkins视图")
@PostMapping("/{externalSystemId}/sync-views")
public Response<Void> syncViews(
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
) {
jenkinsManagerService.syncViews(externalSystemId);
return Response.success();
}
@Operation(summary = "同步Jenkins任务")
@PostMapping("/{externalSystemId}/sync-jobs")
public Response<Void> syncJobs(
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
) {
jenkinsManagerService.syncJobs(externalSystemId);
return Response.success();
}
@Operation(summary = "同步Jenkins构建信息")
@PostMapping("/{externalSystemId}/sync-builds")
public Response<Void> syncBuilds(
@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
) {
jenkinsManagerService.syncBuilds(externalSystemId);
return Response.success();
}
@Operation(summary = "获取Jenkins实例信息")
@GetMapping("/{externalSystemId}/instance")
public Response<JenkinsInstanceDTO> instance(@Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId) {
return Response.success(jenkinsManagerService.instance(externalSystemId));
}
}

View File

@ -1,13 +1,17 @@
package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
import com.qqchen.deploy.backend.deploy.dto.JenkinsViewDTO;
import com.qqchen.deploy.backend.deploy.query.JenkinsViewQuery;
import com.qqchen.deploy.backend.deploy.service.IJenkinsViewService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
@ -20,6 +24,18 @@ import java.util.List;
@Tag(name = "Jenkins视图管理", description = "Jenkins视图管理相关接口")
public class JenkinsViewApiController extends BaseController<JenkinsView, JenkinsViewDTO, Long, JenkinsViewQuery> {
@Resource
private IJenkinsViewService jenkinsViewService;
@Operation(summary = "同步Jenkins视图", description = "异步同步指定外部系统的所有Jenkins视图立即返回")
@PostMapping("/sync")
public Response<Void> sync(
@Parameter(description = "外部系统ID", required = true) @RequestParam Long externalSystemId
) {
jenkinsViewService.syncViews(externalSystemId);
return Response.success();
}
@Override
protected void exportData(HttpServletResponse response, List<JenkinsViewDTO> data) {
// TODO: 实现导出逻辑

View File

@ -34,4 +34,9 @@ public class JenkinsJobDTO extends BaseDTO {
private Long viewId;
/**
* 关联的构建数量仅在列表和分页查询时填充
*/
private Long buildCount;
}

View File

@ -20,4 +20,9 @@ public class JenkinsViewDTO extends BaseDTO {
private String viewUrl;
/**
* 关联的任务数量仅在列表和分页查询时填充
*/
private Long jobCount;
}

View File

@ -42,4 +42,12 @@ public interface IJenkinsBuildRepository extends IBaseRepository<JenkinsBuild, L
*/
Optional<JenkinsBuild> findTopByExternalSystemIdAndJobIdOrderByBuildNumberDesc(
Long externalSystemId, Long jobId);
/**
* 统计任务下的构建数量
*
* @param jobId 任务ID
* @return 构建数量
*/
Long countByJobIdAndDeletedFalse(Long jobId);
}

View File

@ -31,4 +31,12 @@ public interface IJenkinsJobRepository extends IBaseRepository<JenkinsJob, Long>
* @return 任务列表
*/
List<JenkinsJob> findByExternalSystemIdAndViewId(Long externalSystemId, Long viewId);
/**
* 统计视图下的任务数量
*
* @param viewId 视图ID
* @return 任务数量
*/
Long countByViewIdAndDeletedFalse(Long viewId);
}

View File

@ -1,5 +1,6 @@
package com.qqchen.deploy.backend.deploy.service;
import com.qqchen.deploy.backend.deploy.dto.JenkinsInstanceDTO;
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.system.model.ExternalSystemDTO;
@ -23,4 +24,20 @@ public interface IExternalSystemService extends IBaseService<ExternalSystem, Ext
* @param enabled 是否启用
*/
void updateStatus(Long id, boolean enabled);
/**
* 获取Jenkins实例信息
*
* @param externalSystemId 外部系统ID
* @return Jenkins实例信息
*/
JenkinsInstanceDTO getJenkinsInstance(Long externalSystemId);
/**
* 获取Git实例信息
*
* @param externalSystemId 外部系统ID
* @return Git实例信息
*/
com.qqchen.deploy.backend.deploy.dto.GitInstanceDTO getGitInstance(Long externalSystemId);
}

View File

@ -14,12 +14,28 @@ import com.qqchen.deploy.backend.deploy.query.JenkinsBuildQuery;
public interface IJenkinsBuildService extends IBaseService<JenkinsBuild, JenkinsBuildDTO, JenkinsBuildQuery, Long> {
/**
* 同步外部系统下所有构建信息
* 同步外部系统下所有构建信息异步执行
*
* @param externalSystemId 外部系统ID
* @return 同步的构建总数
*/
Integer syncAllBuilds(Long externalSystemId);
void syncBuilds(Long externalSystemId);
/**
* 同步指定视图下的构建信息异步执行
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID
*/
void syncBuilds(Long externalSystemId, Long viewId);
/**
* 同步指定任务的构建信息异步执行
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID
* @param jobId 任务ID
*/
void syncBuilds(Long externalSystemId, Long viewId, Long jobId);
/**
* 根据外部系统ID统计构建总数

View File

@ -23,12 +23,19 @@ public interface IJenkinsJobService extends IBaseService<JenkinsJob, JenkinsJobD
Integer syncJobsByView(ExternalSystem externalSystem, JenkinsView view);
/**
* 同步外部系统下所有视图的Jenkins任务
* 同步外部系统下所有视图的Jenkins任务异步执行
*
* @param externalSystemId 外部系统ID
* @return 同步的任务总数
*/
Integer syncJobs(Long externalSystemId);
void syncJobs(Long externalSystemId);
/**
* 同步指定视图下的Jenkins任务异步执行
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID
*/
void syncJobs(Long externalSystemId, Long viewId);
/**
* 根据外部系统ID查询所有任务

View File

@ -1,39 +0,0 @@
package com.qqchen.deploy.backend.deploy.service;
import com.qqchen.deploy.backend.deploy.dto.JenkinsInstanceDTO;
/**
* Jenkins管理服务接口
*/
public interface IJenkinsManagerService {
/**
* 同步Jenkins所有数据视图任务构建信息
*
* @param externalSystemId 外部系统ID
*/
void syncAll(Long externalSystemId);
/**
* 同步Jenkins视图
*
* @param externalSystemId 外部系统ID
*/
void syncViews(Long externalSystemId);
/**
* 同步Jenkins任务
*
* @param externalSystemId 外部系统ID
*/
void syncJobs(Long externalSystemId);
/**
* 同步Jenkins构建信息
*
* @param externalSystemId 外部系统ID
*/
void syncBuilds(Long externalSystemId);
JenkinsInstanceDTO instance(Long externalSystemId);
}

View File

@ -12,12 +12,11 @@ import java.util.List;
public interface IJenkinsViewService extends IBaseService<JenkinsView, JenkinsViewDTO, JenkinsViewQuery, Long> {
/**
* 同步Jenkins视图
* 同步Jenkins视图异步执行
*
* @param externalSystemId 外部系统ID
* @return 同步的视图数量
*/
Integer syncViews(Long externalSystemId);
void syncViews(Long externalSystemId);
/**
* 根据外部系统ID查询所有视图

View File

@ -1,6 +1,18 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.deploy.dto.*;
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
import com.qqchen.deploy.backend.deploy.entity.JenkinsSyncHistory;
import com.qqchen.deploy.backend.deploy.entity.RepositorySyncHistory;
import com.qqchen.deploy.backend.deploy.enums.ExternalSystemSyncStatus;
import com.qqchen.deploy.backend.deploy.enums.JenkinsSyncType;
import com.qqchen.deploy.backend.deploy.enums.RepositorySyncType;
import com.qqchen.deploy.backend.deploy.repository.IJenkinsSyncHistoryRepository;
import com.qqchen.deploy.backend.deploy.repository.IRepositorySyncHistoryRepository;
import com.qqchen.deploy.backend.deploy.service.*;
import com.qqchen.deploy.backend.deploy.service.IJenkinsBuildService;
import com.qqchen.deploy.backend.deploy.service.IJenkinsJobService;
import com.qqchen.deploy.backend.deploy.service.IJenkinsViewService;
import com.qqchen.deploy.backend.system.enums.ExternalSystemAuthTypeEnum;
import com.qqchen.deploy.backend.system.enums.ExternalSystemSyncStatusEnum;
import com.qqchen.deploy.backend.system.enums.ExternalSystemTypeEnum;
@ -51,6 +63,30 @@ public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, E
private List<IExternalSystemIntegration> systemIntegrations;
private Map<ExternalSystemTypeEnum, IExternalSystemIntegration> integrationMap;
@Resource
private IJenkinsViewService jenkinsViewService;
@Resource
private IJenkinsJobService jenkinsJobService;
@Resource
private IJenkinsBuildService jenkinsBuildService;
@Resource
private IJenkinsSyncHistoryRepository jenkinsSyncHistoryRepository;
@Resource
private IRepositoryGroupService repositoryGroupService;
@Resource
private IRepositoryProjectService repositoryProjectService;
@Resource
private IRepositoryBranchService repositoryBranchService;
@Resource
private IRepositorySyncHistoryRepository repositorySyncHistoryRepository;
@PostConstruct
public void init() {
@ -129,4 +165,89 @@ public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, E
externalSystemRepository.save(system);
}
@Override
public JenkinsInstanceDTO getJenkinsInstance(Long externalSystemId) {
// 1. 创建返回对象
JenkinsInstanceDTO instanceDTO = new JenkinsInstanceDTO();
// 2. 获取视图列表
List<JenkinsViewDTO> views = jenkinsViewService.findByExternalSystemId(externalSystemId);
instanceDTO.setJenkinsViewList(views);
instanceDTO.setTotalViews(views.size());
// 3. 获取任务列表
List<JenkinsJobDTO> jobs = jenkinsJobService.findByExternalSystemId(externalSystemId);
instanceDTO.setJenkinsJobList(jobs);
instanceDTO.setTotalJobs(jobs.size());
// 4. 获取构建总数
Long totalBuilds = jenkinsBuildService.countByExternalSystemId(externalSystemId);
instanceDTO.setTotalBuilds(totalBuilds.intValue());
// 5. 获取最后同步时间
JenkinsSyncHistory lastViewSync = jenkinsSyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, JenkinsSyncType.VIEW, ExternalSystemSyncStatus.SUCCESS);
if (lastViewSync != null) {
instanceDTO.setLastSyncViewsTime(lastViewSync.getEndTime());
}
JenkinsSyncHistory lastJobSync = jenkinsSyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, JenkinsSyncType.JOB, ExternalSystemSyncStatus.SUCCESS);
if (lastJobSync != null) {
instanceDTO.setLastSyncJobsTime(lastJobSync.getEndTime());
}
JenkinsSyncHistory lastBuildSync = jenkinsSyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, JenkinsSyncType.BUILD, ExternalSystemSyncStatus.SUCCESS);
if (lastBuildSync != null) {
instanceDTO.setLastSyncBuildsTime(lastBuildSync.getEndTime());
}
return instanceDTO;
}
@Override
public GitInstanceDTO getGitInstance(Long externalSystemId) {
// 1. 创建返回对象
GitInstanceDTO instanceDTO = new GitInstanceDTO();
// 2. 获取仓库组列表
List<RepositoryGroupDTO> groups = repositoryGroupService.findByExternalSystemId(externalSystemId);
instanceDTO.setRepositoryGroupList(groups);
instanceDTO.setTotalGroups(groups.size());
// 3. 获取项目列表
List<RepositoryProjectDTO> projects = repositoryProjectService.findByExternalSystemId(externalSystemId);
instanceDTO.setRepositoryProjectList(projects);
instanceDTO.setTotalProjects(projects.size());
// 4. 获取分支总数
Long totalBranches = repositoryBranchService.countByExternalSystemId(externalSystemId);
instanceDTO.setTotalBranches(totalBranches.intValue());
// 5. 获取最后同步时间
RepositorySyncHistory lastGroupSync = repositorySyncHistoryRepository
.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, RepositorySyncType.GROUP, ExternalSystemSyncStatus.SUCCESS);
if (lastGroupSync != null) {
instanceDTO.setLastSyncGroupsTime(lastGroupSync.getEndTime());
}
RepositorySyncHistory lastProjectSync = repositorySyncHistoryRepository
.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, RepositorySyncType.PROJECT, ExternalSystemSyncStatus.SUCCESS);
if (lastProjectSync != null) {
instanceDTO.setLastSyncProjectsTime(lastProjectSync.getEndTime());
}
RepositorySyncHistory lastBranchSync = repositorySyncHistoryRepository
.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, RepositorySyncType.BRANCH, ExternalSystemSyncStatus.SUCCESS);
if (lastBranchSync != null) {
instanceDTO.setLastSyncBranchesTime(lastBranchSync.getEndTime());
}
return instanceDTO;
}
}

View File

@ -19,6 +19,7 @@ import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -61,19 +62,10 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override
@Async
@Transactional
public Integer syncAllBuilds(Long externalSystemId) {
// 1. 创建同步上下文
JenkinsSyncContext context = createSyncContext(externalSystemId);
try {
// 2. 执行同步
return doSync(context);
} catch (Exception e) {
// 3. 处理异常
handleSyncException(context, e);
throw e;
}
public void syncBuilds(Long externalSystemId) {
doSyncBuilds(externalSystemId, null, null);
}
private JenkinsSyncContext createSyncContext(Long externalSystemId) {
@ -309,6 +301,80 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
}
}
/**
* 同步指定视图下的构建信息异步执行
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID
*/
@Override
@Async
@Transactional
public void syncBuilds(Long externalSystemId, Long viewId) {
doSyncBuilds(externalSystemId, viewId, null);
}
/**
* 同步指定任务的构建信息异步执行
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID (未使用但为了保持API一致性)
* @param jobId 任务ID
*/
@Override
@Async
@Transactional
public void syncBuilds(Long externalSystemId, Long viewId, Long jobId) {
doSyncBuilds(externalSystemId, viewId, jobId);
}
/**
* 执行构建同步的核心方法
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID可选
* @param jobId 任务ID可选
*/
private void doSyncBuilds(Long externalSystemId, Long viewId, Long jobId) {
// 1. 创建同步上下文
JenkinsSyncContext context = createSyncContext(externalSystemId);
try {
// 2. 根据参数确定同步范围并执行
if (jobId != null) {
// 同步指定任务的构建
JenkinsJob job = jenkinsJobRepository.findById(jobId)
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
JenkinsView view = jenkinsViewRepository.findById(job.getViewId())
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
// 获取该任务的最新状态
List<JenkinsJobResponse> jobResponses = jenkinsServiceIntegration.listJobs(context.getExternalSystem(), view.getViewName());
JenkinsJobResponse jobResponse = jobResponses.stream()
.filter(r -> r.getName().equals(job.getJobName()))
.findFirst()
.orElse(null);
int syncedCount = syncJob(context.getExternalSystem(), job, jobResponse);
log.info("Synchronized {} builds for job: {}", syncedCount, job.getJobName());
} else if (viewId != null) {
// 同步指定视图下的所有构建
JenkinsView view = jenkinsViewRepository.findById(viewId)
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
int syncedCount = syncView(context.getExternalSystem(), view);
log.info("Synchronized {} builds for view: {}", syncedCount, view.getViewName());
} else {
// 全量同步
doSync(context);
}
// 3. 更新同步历史为成功
updateSyncHistorySuccess(context.getSyncHistory());
log.info("Successfully synchronized builds for external system: {}", externalSystemId);
} catch (Exception e) {
handleSyncException(context, e);
throw e;
}
}
@Override
public Long countByExternalSystemId(Long externalSystemId) {
QJenkinsBuild qJenkinsBuild = QJenkinsBuild.jenkinsBuild;

View File

@ -22,6 +22,7 @@ import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -61,15 +62,41 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
@Resource
private IJenkinsSyncHistoryService jenkinsSyncHistoryService;
@Resource
private com.qqchen.deploy.backend.deploy.repository.IJenkinsBuildRepository jenkinsBuildRepository;
/**
* 同步外部系统下所有视图的Jenkins任务
* 同步外部系统下所有视图的Jenkins任务异步执行
*
* @param externalSystemId 外部系统ID
* @return 同步的任务总数
*/
@Override
@Async
@Transactional(rollbackFor = Exception.class)
public Integer syncJobs(Long externalSystemId) {
public void syncJobs(Long externalSystemId) {
doSyncJobs(externalSystemId, null);
}
/**
* 同步指定视图下的Jenkins任务异步执行
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID
*/
@Override
@Async
@Transactional(rollbackFor = Exception.class)
public void syncJobs(Long externalSystemId, Long viewId) {
doSyncJobs(externalSystemId, viewId);
}
/**
* 执行任务同步的核心方法
*
* @param externalSystemId 外部系统ID
* @param viewId 视图ID可选
*/
private void doSyncJobs(Long externalSystemId, Long viewId) {
// 1. 创建同步历史记录
JenkinsSyncHistoryDTO syncHistory = new JenkinsSyncHistoryDTO();
syncHistory.setExternalSystemId(externalSystemId);
@ -79,19 +106,29 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
try {
// 2. 查询外部系统
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId).orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
.orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
// 3. 查询该外部系统下的所有视图
List<JenkinsView> views = jenkinsViewRepository.findByExternalSystemId(externalSystemId);
if (views.isEmpty()) {
log.info("No views found for external system: {}", externalSystemId);
// 更新同步历史为成功
syncHistory.setStatus(ExternalSystemSyncStatus.SUCCESS);
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
return 0;
// 3. 确定要同步的视图列表
List<JenkinsView> views;
if (viewId != null) {
// 同步指定视图
JenkinsView view = jenkinsViewRepository.findById(viewId)
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
views = List.of(view);
} else {
// 同步所有视图
views = jenkinsViewRepository.findByExternalSystemId(externalSystemId);
}
// 4. 遍历所有视图同步每个视图下的任务
if (views.isEmpty()) {
log.info("No views found for external system: {}", externalSystemId);
syncHistory.setStatus(ExternalSystemSyncStatus.SUCCESS);
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
return;
}
// 4. 遍历视图同步每个视图下的任务
int totalSyncedJobs = 0;
StringBuilder errorMessages = new StringBuilder();
for (JenkinsView view : views) {
@ -117,10 +154,8 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
log.info("Successfully synchronized total {} jobs for external system: {}", totalSyncedJobs, externalSystemId);
return totalSyncedJobs;
} catch (Exception e) {
log.error("Failed to sync Jenkins jobs for external system: {}", externalSystemId, e);
// 更新同步历史为失败
syncHistory.setStatus(ExternalSystemSyncStatus.FAILED);
syncHistory.setErrorMessage(e.getMessage());
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
@ -285,4 +320,32 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
query.setExternalSystemId(externalSystemId);
return super.findAll(query);
}
/**
* 重写分页方法增加关联构建数统计
*/
@Override
public org.springframework.data.domain.Page<JenkinsJobDTO> page(JenkinsJobQuery query) {
org.springframework.data.domain.Page<JenkinsJobDTO> page = super.page(query);
// 填充每个任务的构建数量
page.getContent().forEach(dto -> {
Long buildCount = jenkinsBuildRepository.countByJobIdAndDeletedFalse(dto.getId());
dto.setBuildCount(buildCount);
});
return page;
}
/**
* 重写列表方法增加关联构建数统计
*/
@Override
public List<JenkinsJobDTO> findAll(JenkinsJobQuery query) {
List<JenkinsJobDTO> list = super.findAll(query);
// 填充每个任务的构建数量
list.forEach(dto -> {
Long buildCount = jenkinsBuildRepository.countByJobIdAndDeletedFalse(dto.getId());
dto.setBuildCount(buildCount);
});
return list;
}
}

View File

@ -1,117 +0,0 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.deploy.dto.JenkinsInstanceDTO;
import com.qqchen.deploy.backend.deploy.dto.JenkinsJobDTO;
import com.qqchen.deploy.backend.deploy.dto.JenkinsViewDTO;
import com.qqchen.deploy.backend.deploy.entity.JenkinsJob;
import com.qqchen.deploy.backend.deploy.entity.JenkinsView;
import com.qqchen.deploy.backend.deploy.service.IJenkinsManagerService;
import com.qqchen.deploy.backend.deploy.service.IJenkinsViewService;
import com.qqchen.deploy.backend.deploy.service.IJenkinsJobService;
import com.qqchen.deploy.backend.deploy.service.IJenkinsBuildService;
import com.qqchen.deploy.backend.deploy.service.IJenkinsSyncHistoryService;
import com.qqchen.deploy.backend.deploy.entity.JenkinsSyncHistory;
import com.qqchen.deploy.backend.deploy.enums.ExternalSystemSyncStatus;
import com.qqchen.deploy.backend.deploy.enums.JenkinsSyncType;
import com.qqchen.deploy.backend.deploy.repository.IJenkinsSyncHistoryRepository;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Jenkins管理服务实现
*/
@Slf4j
@Service
public class JenkinsManagerServiceImpl implements IJenkinsManagerService {
@Resource
private IJenkinsViewService jenkinsViewService;
@Resource
private IJenkinsJobService jenkinsJobService;
@Resource
private IJenkinsBuildService jenkinsBuildService;
@Resource
private IJenkinsSyncHistoryRepository jenkinsSyncHistoryRepository;
@Override
@Transactional(rollbackFor = Exception.class)
public void syncAll(Long externalSystemId) {
// 同步视图
syncViews(externalSystemId);
// 同步任务
syncJobs(externalSystemId);
// 同步构建信息
syncBuilds(externalSystemId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void syncViews(Long externalSystemId) {
// 同步视图
Integer viewCount = jenkinsViewService.syncViews(externalSystemId);
log.info("Successfully synchronized {} views", viewCount);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void syncJobs(Long externalSystemId) {
// 同步任务
Integer jobCount = jenkinsJobService.syncJobs(externalSystemId);
log.info("Successfully synchronized {} jobs", jobCount);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void syncBuilds(Long externalSystemId) {
// 同步构建信息
Integer buildCount = jenkinsBuildService.syncAllBuilds(externalSystemId);
log.info("Successfully synchronized {} builds", buildCount);
}
@Override
public JenkinsInstanceDTO instance(Long externalSystemId) {
// 1. 创建返回对象
JenkinsInstanceDTO instanceDTO = new JenkinsInstanceDTO();
// 2. 获取视图列表
List<JenkinsViewDTO> views = jenkinsViewService.findByExternalSystemId(externalSystemId);
instanceDTO.setJenkinsViewList(views);
instanceDTO.setTotalViews(views.size());
// 3. 获取任务列表
List<JenkinsJobDTO> jobs = jenkinsJobService.findByExternalSystemId(externalSystemId);
instanceDTO.setJenkinsJobList(jobs);
instanceDTO.setTotalJobs(jobs.size());
// 4. 获取构建总数
Long totalBuilds = jenkinsBuildService.countByExternalSystemId(externalSystemId);
instanceDTO.setTotalBuilds(totalBuilds.intValue());
// 5. 获取最后同步时间
JenkinsSyncHistory lastViewSync = jenkinsSyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, JenkinsSyncType.VIEW, ExternalSystemSyncStatus.SUCCESS);
if (lastViewSync != null) {
instanceDTO.setLastSyncViewsTime(lastViewSync.getEndTime());
}
JenkinsSyncHistory lastJobSync = jenkinsSyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, JenkinsSyncType.JOB, ExternalSystemSyncStatus.SUCCESS);
if (lastJobSync != null) {
instanceDTO.setLastSyncJobsTime(lastJobSync.getEndTime());
}
JenkinsSyncHistory lastBuildSync = jenkinsSyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
externalSystemId, JenkinsSyncType.BUILD, ExternalSystemSyncStatus.SUCCESS);
if (lastBuildSync != null) {
instanceDTO.setLastSyncBuildsTime(lastBuildSync.getEndTime());
}
return instanceDTO;
}
}

View File

@ -20,6 +20,7 @@ import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -44,6 +45,9 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
@Resource
private IJenkinsServiceIntegration jenkinsServiceIntegration;
@Resource
private com.qqchen.deploy.backend.deploy.repository.IJenkinsJobRepository jenkinsJobRepository;
@Resource
private JenkinsViewConverter jenkinsViewConverter;
@ -54,14 +58,14 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
private IJenkinsSyncHistoryService jenkinsSyncHistoryService;
/**
* 同步Jenkins视图
* 同步Jenkins视图异步执行
*
* @param externalSystemId 外部系统ID
* @return 同步的视图数量
*/
@Override
@Async
@Transactional(rollbackFor = Exception.class)
public Integer syncViews(Long externalSystemId) {
public void syncViews(Long externalSystemId) {
// 1. 创建同步历史记录
JenkinsSyncHistoryDTO syncHistory = new JenkinsSyncHistoryDTO();
syncHistory.setExternalSystemId(externalSystemId);
@ -80,7 +84,7 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
// 更新同步历史为成功
syncHistory.setStatus(ExternalSystemSyncStatus.SUCCESS);
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
return 0;
return;
}
// 4. 转换并保存/更新视图数据
@ -114,8 +118,6 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
// 6. 更新同步历史为成功
syncHistory.setStatus(ExternalSystemSyncStatus.SUCCESS);
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
return jenkinsViews.size();
} catch (Exception e) {
log.error("Failed to sync Jenkins views for external system: {}", externalSystemId, e);
syncHistory.setStatus(ExternalSystemSyncStatus.FAILED);
@ -139,4 +141,32 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
query.setExternalSystemId(externalSystemId);
return super.findAll(query);
}
/**
* 重写分页方法增加关联任务数统计
*/
@Override
public org.springframework.data.domain.Page<JenkinsViewDTO> page(JenkinsViewQuery query) {
org.springframework.data.domain.Page<JenkinsViewDTO> page = super.page(query);
// 填充每个视图的任务数量
page.getContent().forEach(dto -> {
Long jobCount = jenkinsJobRepository.countByViewIdAndDeletedFalse(dto.getId());
dto.setJobCount(jobCount);
});
return page;
}
/**
* 重写列表方法增加关联任务数统计
*/
@Override
public List<JenkinsViewDTO> findAll(JenkinsViewQuery query) {
List<JenkinsViewDTO> list = super.findAll(query);
// 填充每个视图的任务数量
list.forEach(dto -> {
Long jobCount = jenkinsJobRepository.countByViewIdAndDeletedFalse(dto.getId());
dto.setJobCount(jobCount);
});
return list;
}
}