修改LIQUIBASE的加载方式
This commit is contained in:
parent
e898b25976
commit
a0d38e1d00
@ -216,6 +216,7 @@
|
||||
<dependency>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-core</artifactId>
|
||||
<version>4.25.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import re
|
||||
|
||||
# 读取文件
|
||||
file_path = r'd:\work\java-space\deploy-ease-platform\backend\src\main\resources\db\changelog\changes\v1.0.0-data.sql'
|
||||
file_path = r'd:\work\java-space\deploy-ease-platform\backend\src\main\resources\db\changelog\init\v1.0.0-data.sql'
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
@ -62,7 +62,7 @@ public class DeployApiController {
|
||||
@GetMapping("/records/{deployRecordId}/flow-graph")
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
public Response<DeployRecordFlowGraphDTO> getDeployFlowGraph(
|
||||
@Parameter(description = "部署记录ID", required = true) @PathVariable Long deployRecordId
|
||||
@Parameter(description = "部署记录ID", required = true) @PathVariable Long deployRecordId
|
||||
) {
|
||||
return Response.success(deployRecordService.getDeployFlowGraph(deployRecordId));
|
||||
}
|
||||
@ -73,13 +73,9 @@ public class DeployApiController {
|
||||
@Operation(summary = "获取我的部署审批任务", description = "查询当前登录用户待审批的部署任务,支持按团队和环境筛选")
|
||||
@GetMapping("/my-approval-tasks")
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
public Response<List<DeployApprovalTaskDTO>> getMyApprovalTasks(
|
||||
@Parameter(description = "团队ID(可选,用于筛选指定团队的审批任务)")
|
||||
@RequestParam(required = false) Long teamId,
|
||||
@Parameter(description = "环境ID(可选,用于筛选指定环境的审批任务)")
|
||||
@RequestParam(required = false) Long environmentId,
|
||||
@Parameter(description = "工作流定义Key列表(可选,支持查询多个工作流的待审批任务)")
|
||||
@RequestParam(required = false) List<String> workflowDefinitionKeys
|
||||
public Response<List<DeployApprovalTaskDTO>> getMyApprovalTasks(@Parameter(description = "团队ID(可选,用于筛选指定团队的审批任务)") @RequestParam(required = false) Long teamId,
|
||||
@Parameter(description = "环境ID(可选,用于筛选指定环境的审批任务)") @RequestParam(required = false) Long environmentId,
|
||||
@Parameter(description = "工作流定义Key列表(可选,支持查询多个工作流的待审批任务)") @RequestParam(required = false) List<String> workflowDefinitionKeys
|
||||
) {
|
||||
return Response.success(deployService.getMyApprovalTasks(teamId, environmentId, workflowDefinitionKeys));
|
||||
}
|
||||
@ -94,7 +90,7 @@ public class DeployApiController {
|
||||
deployService.completeApproval(request);
|
||||
return Response.success();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取节点日志
|
||||
*/
|
||||
|
||||
@ -244,7 +244,7 @@ public class GitServiceIntegrationImpl extends BaseExternalSystemIntegration imp
|
||||
}
|
||||
|
||||
if (!allBranches.isEmpty()) {
|
||||
log.info("Total fetched {} branches for project: {}, first branch: {}",
|
||||
log.debug("Total fetched {} branches for project: {}, first branch: {}",
|
||||
allBranches.size(), projectId, allBranches.getFirst().getName());
|
||||
} else {
|
||||
log.warn("No branches found for project: {}", projectId);
|
||||
|
||||
@ -83,10 +83,10 @@ public class ServerMonitorScheduler {
|
||||
config.setServerOfflineTemplateId(serverOfflineTemplateId);
|
||||
config.setResourceAlertTemplateId(resourceAlertTemplateId);
|
||||
|
||||
log.info("========== 开始采集服务器监控数据 ========== channelId={}, offlineTemplateId={}, alertTemplateId={}",
|
||||
log.debug("开始采集服务器监控数据: channelId={}, offlineTemplateId={}, alertTemplateId={}",
|
||||
notificationChannelId, serverOfflineTemplateId, resourceAlertTemplateId);
|
||||
} else {
|
||||
log.info("========== 开始采集服务器监控数据(不发送通知) ==========");
|
||||
log.debug("开始采集服务器监控数据(不发送通知)");
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
@ -99,7 +99,7 @@ public class ServerMonitorScheduler {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("发现 {} 台服务器,开始检测在线状态并采集监控数据", allServers.size());
|
||||
log.debug("发现 {} 台服务器,开始检测在线状态并采集监控数据", allServers.size());
|
||||
|
||||
// 2. 并发检测所有服务器的连接状态并采集监控数据
|
||||
// - 连接失败 → 发送离线通知
|
||||
@ -130,7 +130,7 @@ public class ServerMonitorScheduler {
|
||||
// 5. 批量保存监控数据到数据库
|
||||
if (!monitorDataList.isEmpty()) {
|
||||
monitorService.batchSaveMonitorData(monitorDataList);
|
||||
log.info("监控数据已保存到数据库: count={}", monitorDataList.size());
|
||||
log.debug("监控数据已保存到数据库: count={}", monitorDataList.size());
|
||||
}
|
||||
|
||||
// 6. 检查告警规则(优化:只查询一次规则)
|
||||
@ -206,16 +206,15 @@ public class ServerMonitorScheduler {
|
||||
server.setLastConnectTime(LocalDateTime.now());
|
||||
serverRepository.save(server);
|
||||
|
||||
log.debug("服务器连接成功: serverId={}, name={}, ip={}",
|
||||
server.getId(), server.getServerName(), server.getHostIp());
|
||||
log.info("✓ 服务器连接成功: {} ({})", server.getServerName(), server.getHostIp());
|
||||
|
||||
// 4. 采集监控数据(复用同一个SSH连接)
|
||||
return collectServerMonitorData(server, sshClient, sshService);
|
||||
|
||||
} catch (Exception e) {
|
||||
// 连接失败,更新服务器状态为离线
|
||||
log.error("服务器连接失败: serverId={}, name={}, ip={}, error={}",
|
||||
server.getId(), server.getServerName(), server.getHostIp(), e.getMessage());
|
||||
log.error("✗ 服务器连接失败: {} ({}) - {}",
|
||||
server.getServerName(), server.getHostIp(), e.getMessage());
|
||||
|
||||
server.setStatus(ServerStatusEnum.OFFLINE);
|
||||
serverRepository.save(server);
|
||||
@ -260,7 +259,7 @@ public class ServerMonitorScheduler {
|
||||
// 3. 发送通知(NotificationService会自动根据渠道类型创建请求对象)
|
||||
notificationService.send(request);
|
||||
|
||||
log.info("✅ 服务器离线通知已发送: serverId={}, serverName={}, ip={}",
|
||||
log.info("服务器离线通知已发送: serverId={}, serverName={}, ip={}",
|
||||
server.getId(), server.getServerName(), server.getHostIp());
|
||||
} catch (Exception e) {
|
||||
log.error("发送服务器离线通知异常: serverId={}", server.getId(), e);
|
||||
@ -380,7 +379,7 @@ public class ServerMonitorScheduler {
|
||||
* 此方法由定时任务管理系统调用,建议每天凌晨执行
|
||||
*/
|
||||
public void cleanOldMonitorData() {
|
||||
log.info("========== 开始清理历史监控数据 ==========");
|
||||
log.debug("开始清理历史监控数据");
|
||||
|
||||
try {
|
||||
// 删除30天前的数据
|
||||
|
||||
@ -25,6 +25,7 @@ import com.qqchen.deploy.backend.workflow.dto.WorkflowNodeLogDTO;
|
||||
import com.qqchen.deploy.backend.workflow.dto.inputmapping.ApprovalInputMapping;
|
||||
import com.qqchen.deploy.backend.workflow.dto.outputs.ApprovalOutputs;
|
||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnums;
|
||||
import com.qqchen.deploy.backend.workflow.model.NodeContext;
|
||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
||||
import com.qqchen.deploy.backend.workflow.service.IWorkflowInstanceService;
|
||||
@ -826,6 +827,11 @@ public class DeployServiceImpl implements IDeployService {
|
||||
|
||||
WorkflowDefinition workflowDefinition = workflowDefinitionRepository.findById(teamApp.getWorkflowDefinitionId()).orElseThrow(() -> new BusinessException(ResponseCode.DEPLOY_WORKFLOW_NOT_CONFIGURED));
|
||||
|
||||
// 2. 检查工作流是否已发布
|
||||
if (workflowDefinition.getStatus() != WorkflowDefinitionStatusEnums.PUBLISHED) {
|
||||
throw new BusinessException(ResponseCode.WORKFLOW_NOT_PUBLISHED);
|
||||
}
|
||||
|
||||
// 2. 生成业务标识(使用前端传入的 executionNo)
|
||||
String businessKey = UUID.randomUUID().toString();
|
||||
|
||||
@ -922,7 +928,7 @@ public class DeployServiceImpl implements IDeployService {
|
||||
List<Task> tasks = taskQuery.list();
|
||||
|
||||
if (tasks.isEmpty()) {
|
||||
log.info("用户 {} 当前没有待办审批任务", currentUsername);
|
||||
log.debug("用户 {} 当前没有待办审批任务", currentUsername);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@ -153,7 +153,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
// 1. 获取所有视图
|
||||
List<JenkinsView> views = jenkinsViewRepository.findByExternalSystemId(context.getExternalSystem().getId());
|
||||
if (views.isEmpty()) {
|
||||
log.info("No views found for external system: {}", context.getExternalSystem().getId());
|
||||
log.debug("No views found for external system: {}", context.getExternalSystem().getId());
|
||||
updateSyncHistorySuccess(context.getSyncHistory());
|
||||
return 0;
|
||||
}
|
||||
@ -200,7 +200,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
// 2. 一次性获取视图下所有任务的最新状态
|
||||
List<JenkinsJobResponse> jobResponses = jenkinsServiceIntegration.listJobs(externalSystem, view.getViewName());
|
||||
if (jobResponses.isEmpty()) {
|
||||
log.info("No job information available for view: {}", view.getViewName());
|
||||
log.debug("No job information available for view: {}", view.getViewName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -273,7 +273,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (newBuilds.isEmpty()) {
|
||||
log.info("No new builds found for job: {} (from: {}, to: {})", job.getJobName(), fromBuildNumber, latestBuildNumber);
|
||||
log.debug("No new builds found for job: {} (from: {}, to: {})", job.getJobName(), fromBuildNumber, latestBuildNumber);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
jenkinsBuilds.add(build);
|
||||
}
|
||||
|
||||
log.info("Saving {} builds for job: {}", jenkinsBuilds.size(), job.getJobName());
|
||||
log.debug("Saving {} builds for job: {}", jenkinsBuilds.size(), job.getJobName());
|
||||
jenkinsBuildRepository.saveAll(jenkinsBuilds);
|
||||
}
|
||||
|
||||
@ -423,13 +423,13 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
int syncedCount = syncJob(context.getExternalSystem(), job, jobResponse);
|
||||
log.info("Synchronized {} builds for job: {}", syncedCount, job.getJobName());
|
||||
log.debug("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());
|
||||
log.debug("Synchronized {} builds for view: {}", syncedCount, view.getViewName());
|
||||
} else {
|
||||
// 全量同步
|
||||
doSync(context);
|
||||
@ -456,7 +456,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
* </ol>
|
||||
*/
|
||||
private void checkBuildNotifications(Long externalSystemId) {
|
||||
log.info("开始检查构建通知: externalSystemId={}", externalSystemId);
|
||||
log.debug("开始检查构建通知: externalSystemId={}", externalSystemId);
|
||||
|
||||
try {
|
||||
// 1. 获取外部系统信息
|
||||
@ -470,7 +470,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
List<TeamApplication> teamApps = teamApplicationRepository
|
||||
.findByDeploySystemIdAndBuildType(externalSystemId, BuildTypeEnum.JENKINS);
|
||||
if (teamApps.isEmpty()) {
|
||||
log.info("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
||||
log.debug("没有团队绑定该Jenkins系统: externalSystemId={}", externalSystemId);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
.filter(ta -> ta.getDeployJob() != null && !ta.getDeployJob().isEmpty())
|
||||
.collect(Collectors.groupingBy(TeamApplication::getDeployJob));
|
||||
if (teamAppsByJob.isEmpty()) {
|
||||
log.info("没有配置deployJob的团队应用");
|
||||
log.debug("没有配置deployJob的团队应用");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -490,7 +490,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
List<TeamEnvironmentNotificationConfig> configs = teamEnvironmentNotificationConfigRepository
|
||||
.findByTeamIdInAndEnvironmentIdInAndBuildNotificationEnabledTrue(teamIds, envIds);
|
||||
if (configs.isEmpty()) {
|
||||
log.info("没有团队启用构建通知");
|
||||
log.debug("没有团队启用构建通知");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -540,7 +540,7 @@ public class JenkinsBuildServiceImpl extends BaseServiceImpl<JenkinsBuild, Jenki
|
||||
}
|
||||
|
||||
if (latestBuildByJobId.isEmpty()) {
|
||||
log.info("没有需要处理的构建记录");
|
||||
log.debug("没有需要处理的构建记录");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -144,7 +144,7 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
}
|
||||
|
||||
if (views.isEmpty()) {
|
||||
log.info("No views found for external system: {}", externalSystemId);
|
||||
log.debug("No views found for external system: {}", externalSystemId);
|
||||
syncHistory.setStatus(ExternalSystemSyncStatus.SUCCESS);
|
||||
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
|
||||
return;
|
||||
@ -198,7 +198,7 @@ public class JenkinsJobServiceImpl extends BaseServiceImpl<JenkinsJob, JenkinsJo
|
||||
// 1. 获取Jenkins任务列表
|
||||
List<JenkinsJobResponse> jobResponses = jenkinsServiceIntegration.listJobs(externalSystem, view.getViewName());
|
||||
if (jobResponses.isEmpty()) {
|
||||
log.info("No jobs found in Jenkins view: {}", view.getViewName());
|
||||
log.debug("No jobs found in Jenkins view: {}", view.getViewName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ public class JenkinsViewServiceImpl extends BaseServiceImpl<JenkinsView, Jenkins
|
||||
// 3. 调用Jenkins API获取视图列表
|
||||
List<JenkinsViewResponse> viewResponses = jenkinsServiceIntegration.listViews(externalSystem);
|
||||
if (viewResponses.isEmpty()) {
|
||||
log.info("No views found in Jenkins system: {}", externalSystemId);
|
||||
log.debug("No views found in Jenkins system: {}", externalSystemId);
|
||||
// 更新同步历史为成功
|
||||
syncHistory.setStatus(ExternalSystemSyncStatus.SUCCESS);
|
||||
jenkinsSyncHistoryService.saveOrUpdateHistory(syncHistory);
|
||||
|
||||
@ -298,11 +298,11 @@ public class RepositoryBranchServiceImpl extends BaseServiceImpl<RepositoryBranc
|
||||
for (RepositoryProject project : projects) {
|
||||
CompletableFuture<List<RepositoryBranch>> future = CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
log.info("Syncing branches for project: {} (ID: {}, GitLab ID: {})", project.getName(), project.getId(), project.getRepoProjectId());
|
||||
log.debug("Syncing branches for project: {} (ID: {}, GitLab ID: {})", project.getName(), project.getId(), project.getRepoProjectId());
|
||||
|
||||
// 5.1 获取当前项目在GitLab上的所有分支
|
||||
List<GitBranchResponse> remoteBranches = gitServiceIntegration.branches(externalSystem, project.getRepoProjectId());
|
||||
log.info("Found {} remote branches for project: {}", remoteBranches.size(), project.getName());
|
||||
log.debug("Found {} remote branches for project: {}", remoteBranches.size(), project.getName());
|
||||
|
||||
List<RepositoryBranch> branchesToUpdate = new ArrayList<>();
|
||||
Set<String> processedBranches = new HashSet<>();
|
||||
@ -338,7 +338,7 @@ public class RepositoryBranchServiceImpl extends BaseServiceImpl<RepositoryBranc
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Processed {} branches for project: {}", branchesToUpdate.size(), project.getName());
|
||||
log.debug("Processed {} branches for project: {}", branchesToUpdate.size(), project.getName());
|
||||
return branchesToUpdate;
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to sync branches for project: {} (ID: {}, GitLab ID: {})", project.getName(), project.getId(), project.getRepoProjectId(), e);
|
||||
|
||||
@ -91,7 +91,7 @@ public class RepositoryGroupServiceImpl extends BaseServiceImpl<RepositoryGroup,
|
||||
// 3. 从Git API获取所有仓库组信息
|
||||
List<GitGroupResponse> remoteGroups = gitServiceIntegration.groups(externalSystem);
|
||||
if (remoteGroups.isEmpty()) {
|
||||
log.info("No groups found in remote git system: {}", externalSystem.getName());
|
||||
log.debug("No groups found in remote git system: {}", externalSystem.getName());
|
||||
repositorySyncHistoryService.updateSyncHistory(groupHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ public class RepositoryProjectServiceImpl extends BaseServiceImpl<RepositoryProj
|
||||
// 3. 获取需要同步的仓库组列表
|
||||
List<RepositoryGroup> groups = getGroupsToSync(externalSystemId, repoGroupId);
|
||||
if (groups.isEmpty()) {
|
||||
log.info("No groups found for external system: {}", externalSystem.getName());
|
||||
log.debug("No groups found for external system: {}", externalSystem.getName());
|
||||
repositorySyncHistoryService.updateSyncHistory(projectHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -358,7 +358,7 @@ public class TeamApplicationServiceImpl extends BaseServiceImpl<TeamApplication,
|
||||
|
||||
log.info("成功物理删除 {} 条部署记录", deployRecords.size());
|
||||
} else {
|
||||
log.info("团队应用 {} 没有关联的部署记录", id);
|
||||
log.debug("团队应用 {} 没有关联的部署记录", id);
|
||||
}
|
||||
|
||||
// 3. 物理删除团队应用
|
||||
|
||||
@ -263,7 +263,7 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
|
||||
|
||||
// 幂等性检查
|
||||
if (job.getStatus() == ScheduleJobStatusEnum.DISABLED) {
|
||||
log.info("任务已经是禁用状态:jobId={}, jobName={}", jobId, job.getJobName());
|
||||
log.debug("任务已经是禁用状态:jobId={}, jobName={}", jobId, job.getJobName());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -374,14 +374,14 @@ public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJob, Schedul
|
||||
|
||||
@Override
|
||||
public void loadAllEnabledJobs() {
|
||||
log.info("开始加载所有启用的定时任务...");
|
||||
log.debug("开始加载所有启用的定时任务...");
|
||||
|
||||
List<ScheduleJob> enabledJobs = jobRepository.findByStatusAndDeletedFalse(ScheduleJobStatusEnum.ENABLED);
|
||||
|
||||
for (ScheduleJob job : enabledJobs) {
|
||||
try {
|
||||
startJob(job.getId());
|
||||
log.info("加载任务成功:jobId={}, jobName={}", job.getId(), job.getJobName());
|
||||
log.debug("加载任务成功:jobId={}, jobName={}", job.getId(), job.getJobName());
|
||||
} catch (Exception e) {
|
||||
log.error("加载任务失败:jobId={}, jobName={}", job.getId(), job.getJobName(), e);
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ public class SystemReleaseStartupListener {
|
||||
|
||||
log.info("版本发布通知已发送并标记");
|
||||
} else {
|
||||
log.info("没有未通知的版本发布记录");
|
||||
log.debug("没有未通知的版本发布记录");
|
||||
}
|
||||
|
||||
log.info("========================================");
|
||||
|
||||
@ -129,7 +129,10 @@ public class SystemReleaseServiceImpl
|
||||
* 调度维护任务(延迟执行)
|
||||
*/
|
||||
private void scheduleMaintenanceTask(SystemRelease release) {
|
||||
// 计算执行时间
|
||||
// 1. 立即发送维护通知(告知用户系统将在X分钟后维护)
|
||||
sendMaintenanceNotification(release);
|
||||
|
||||
// 2. 计算执行时间
|
||||
Date executeTime = Date.from(
|
||||
LocalDateTime.now()
|
||||
.plusMinutes(release.getDelayMinutes())
|
||||
@ -140,7 +143,7 @@ public class SystemReleaseServiceImpl
|
||||
log.warn("已调度系统维护任务,版本: {}, 执行时间: {}, 预计耗时: {}分钟",
|
||||
release.getReleaseVersion(), executeTime, release.getEstimatedDuration());
|
||||
|
||||
// 延迟执行维护任务,并保存任务引用
|
||||
// 3. 延迟执行维护任务(只负责关闭应用,不再发送通知)
|
||||
ScheduledFuture<?> future = taskScheduler.schedule(() -> {
|
||||
executeMaintenance(release);
|
||||
// 执行完成后从Map中移除
|
||||
@ -154,7 +157,7 @@ public class SystemReleaseServiceImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行维护任务
|
||||
* 执行维护任务(仅负责关闭应用)
|
||||
*/
|
||||
private void executeMaintenance(SystemRelease release) {
|
||||
try {
|
||||
@ -165,26 +168,36 @@ public class SystemReleaseServiceImpl
|
||||
log.warn("自动停止服务: {}", release.getEnableAutoShutdown());
|
||||
log.warn("========================================");
|
||||
|
||||
// 1. 发送维护通知
|
||||
sendMaintenanceNotification(release);
|
||||
|
||||
// 2. 检查是否需要自动停止服务
|
||||
// 1. 检查是否需要自动停止服务
|
||||
if (!Boolean.TRUE.equals(release.getEnableAutoShutdown())) {
|
||||
log.warn("未启用自动停止服务,维护通知已发送,请手动停止服务进行维护");
|
||||
log.warn("未启用自动停止服务,请手动停止服务进行维护");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 等待3秒让通知发出去
|
||||
log.warn("等待3秒,确保通知发送完成...");
|
||||
Thread.sleep(3000);
|
||||
|
||||
// 4. 优雅关闭应用
|
||||
// 2. 优雅关闭应用(使用独立线程,避免调度器死锁)
|
||||
log.warn("系统开始优雅关闭...");
|
||||
((ConfigurableApplicationContext) applicationContext).close();
|
||||
log.info("使用独立线程执行应用关闭,避免调度器死锁");
|
||||
|
||||
// 创建独立的关闭线程
|
||||
Thread shutdownThread = new Thread(() -> {
|
||||
try {
|
||||
// 等待1秒,确保维护任务线程正常退出
|
||||
Thread.sleep(1000);
|
||||
log.warn("执行应用上下文关闭...");
|
||||
((ConfigurableApplicationContext) applicationContext).close();
|
||||
log.warn("应用上下文关闭完成");
|
||||
} catch (Exception e) {
|
||||
log.error("应用关闭失败", e);
|
||||
// 如果优雅关闭失败,强制退出
|
||||
System.exit(1);
|
||||
}
|
||||
}, "app-shutdown-thread");
|
||||
|
||||
shutdownThread.setDaemon(false); // 非守护线程,确保执行完成
|
||||
shutdownThread.start();
|
||||
|
||||
log.info("关闭指令已发出,维护任务线程即将退出");
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.error("系统维护任务被中断", e);
|
||||
} catch (Exception e) {
|
||||
log.error("系统维护任务执行失败", e);
|
||||
}
|
||||
@ -200,16 +213,18 @@ public class SystemReleaseServiceImpl
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND,
|
||||
new Object[]{"通知渠道ID=" + notificationChannelId + "不存在"}));
|
||||
|
||||
// 准备维护通知内容(简化版,只显示关键信息)
|
||||
// 准备维护通知内容(说明将在X分钟后维护)
|
||||
StringBuilder messageBuilder = new StringBuilder();
|
||||
messageBuilder.append(String.format("版本号:%s\n", release.getReleaseVersion()));
|
||||
messageBuilder.append("系统即将开始维护升级\n");
|
||||
messageBuilder.append(String.format("系统将在 %d 分钟后开始维护升级\n", release.getDelayMinutes()));
|
||||
messageBuilder.append(String.format("预计维护时长:%d 分钟\n",
|
||||
release.getEstimatedDuration() != null ? release.getEstimatedDuration() : 10));
|
||||
|
||||
// 如果启用自动停止,增加提示
|
||||
if (Boolean.TRUE.equals(release.getEnableAutoShutdown())) {
|
||||
messageBuilder.append("本次升级程序将自动停止\n");
|
||||
} else {
|
||||
messageBuilder.append("请在维护时间前做好准备\n");
|
||||
}
|
||||
|
||||
messageBuilder.append("\n望周知。");
|
||||
|
||||
@ -41,7 +41,8 @@ spring:
|
||||
# 是否允许JMX管理连接池
|
||||
register-mbeans: true
|
||||
# 连接泄漏检测阈值(毫秒),超过此时间未归还的连接将被记录
|
||||
leak-detection-threshold: 60000
|
||||
# Jenkins 构建轮询最长30分钟,设置为35分钟避免误报
|
||||
leak-detection-threshold: 2100000
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
@ -109,6 +110,8 @@ logging:
|
||||
org.hibernate.orm.jdbc.bind: WARN
|
||||
# 业务日志(保留INFO级别,记录关键业务操作)
|
||||
com.qqchen.deploy.backend: INFO
|
||||
# 屏蔽 SSHJ 底层日志(SecureRandom、Transport 等无业务价值的日志)
|
||||
net.schmizz.sshj: WARN
|
||||
# 日志文件配置
|
||||
file:
|
||||
name: logs/deploy-ease.log # 日志文件路径
|
||||
@ -133,7 +136,8 @@ management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,metrics,info
|
||||
# 添加 threaddump 用于线程监控,heapdump 用于内存分析
|
||||
include: health,metrics,info,threaddump,heapdump,env,loggers
|
||||
metrics:
|
||||
enable:
|
||||
hikari: true
|
||||
|
||||
@ -41,7 +41,8 @@ spring:
|
||||
# 是否允许JMX管理连接池
|
||||
register-mbeans: true
|
||||
# 连接泄漏检测阈值(毫秒),超过此时间未归还的连接将被记录
|
||||
leak-detection-threshold: 60000
|
||||
# Jenkins 构建轮询最长30分钟,设置为35分钟避免误报
|
||||
leak-detection-threshold: 2100000
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
@ -105,6 +106,8 @@ logging:
|
||||
org.hibernate.orm.jdbc.bind: INFO
|
||||
com.qqchen.deploy.backend.framework.utils.EntityPathResolver: DEBUG
|
||||
com.qqchen.deploy.backend: DEBUG
|
||||
# 屏蔽 SSHJ 底层日志(SecureRandom、Transport 等无业务价值的日志)
|
||||
net.schmizz.sshj: WARN
|
||||
# 日志文件配置
|
||||
file:
|
||||
name: logs/deploy-ease.log # 日志文件路径
|
||||
@ -129,7 +132,8 @@ management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,metrics,info
|
||||
# 添加 threaddump 用于线程监控,heapdump 用于内存分析
|
||||
include: health,metrics,info,threaddump,heapdump,env,loggers
|
||||
metrics:
|
||||
enable:
|
||||
hikari: true
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
-- --------------------------------------------------------------------------------------
|
||||
-- 系统版本发布记录 - v1.1
|
||||
-- 功能:记录Jenkins日志优化版本
|
||||
-- 作者:qqchen
|
||||
-- 日期:2025-12-09 14:13
|
||||
-- --------------------------------------------------------------------------------------
|
||||
|
||||
-- 插入 1.1 日志优化发布记录
|
||||
INSERT INTO system_release (
|
||||
create_by, create_time, update_by, update_time, version, deleted,
|
||||
release_version, module, release_date, changes, notified, delay_minutes, estimated_duration, enable_auto_shutdown
|
||||
)
|
||||
VALUES (
|
||||
'system', NOW(), 'system', NOW(), 1, 0,
|
||||
1.11, 'BACKEND', NOW(),
|
||||
'【后端】
|
||||
- 修复:服务器网络流量监控数据异常问题(过滤累计值减少的异常数据)
|
||||
- 修复:服务器测试连接未更新在线状态问题(添加@Transactional事务注解)
|
||||
【前端】
|
||||
- 优化:服务器列表数据加载(卡片/列表模式分别调用 list/page 接口,静默刷新优化体验)
|
||||
- 优化:用户交互体验(表单必填校验、硬件采集详细反馈、操作流程简化)',
|
||||
0, NULL, NULL, 0
|
||||
);
|
||||
@ -6,6 +6,6 @@
|
||||
|
||||
<!-- Jenkins构建同步日志优化 - 无数据库变更 -->
|
||||
<changeSet id="20251209141300" author="qqchen">
|
||||
<sqlFile path="20251209141300-01.sql" relativeToChangelogFile="true"/>
|
||||
<sqlFile path="../sql/20251209141300-01.sql" relativeToChangelogFile="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
||||
@ -28,7 +28,8 @@
|
||||
</rollback>
|
||||
</changeSet>
|
||||
|
||||
<!-- 自动加载 changes 目录下的所有 XML changelog -->
|
||||
<includeAll path="changes/" relativeToChangelogFile="true" errorIfMissingOrEmpty="false"/>
|
||||
|
||||
<!-- 自动加载 changes 目录下的所有 XML changelog(SQL 文件已分离到外层 sql/ 目录) -->
|
||||
<includeAll path="changes/"
|
||||
relativeToChangelogFile="true"
|
||||
errorIfMissingOrEmpty="false"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
databaseChangeLog:
|
||||
- changeSet:
|
||||
id: v1.0.0-schema
|
||||
author: qqchen
|
||||
runOnChange: false
|
||||
failOnError: true
|
||||
comment: "初始化数据库表结构"
|
||||
sqlFile:
|
||||
path: db/changelog/changes/v1.0.0-schema.sql
|
||||
stripComments: false
|
||||
splitStatements: true
|
||||
endDelimiter: ";"
|
||||
rollback:
|
||||
- empty
|
||||
|
||||
- changeSet:
|
||||
id: v1.0.0-data
|
||||
author: qqchen
|
||||
runOnChange: false
|
||||
failOnError: true
|
||||
comment: "初始化基础数据"
|
||||
context: "!test"
|
||||
sqlFile:
|
||||
path: db/changelog/changes/v1.0.0-data.sql
|
||||
stripComments: false
|
||||
splitStatements: true
|
||||
endDelimiter: ";"
|
||||
rollback:
|
||||
- empty
|
||||
|
||||
- changeSet:
|
||||
id: 20251209112700
|
||||
author: qqchen
|
||||
runOnChange: false
|
||||
failOnError: true
|
||||
comment: "系统版本发布记录 - v1.5.0初始数据"
|
||||
sqlFile:
|
||||
path: db/changelog/changes/20251209112700-01.sql
|
||||
stripComments: false
|
||||
splitStatements: true
|
||||
endDelimiter: ";"
|
||||
rollback:
|
||||
- empty
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,27 @@
|
||||
-- --------------------------------------------------------------------------------------
|
||||
-- 系统版本发布记录 - v1.1
|
||||
-- 功能:记录Jenkins日志优化版本
|
||||
-- 作者:qqchen
|
||||
-- 日期:2025-12-09 14:13
|
||||
-- --------------------------------------------------------------------------------------
|
||||
|
||||
-- 插入 1.1 日志优化发布记录
|
||||
INSERT INTO system_release (
|
||||
create_by, create_time, update_by, update_time, version, deleted,
|
||||
release_version, module, release_date, changes, notified, delay_minutes, estimated_duration, enable_auto_shutdown
|
||||
)
|
||||
VALUES (
|
||||
'system', NOW(), 'system', NOW(), 1, 0,
|
||||
1.12, 'ALL', NOW(),
|
||||
'【后端】
|
||||
- 优化:生产环境日志级别(空结果/开始日志/详细过程调整为DEBUG,减少冗余输出)
|
||||
- 优化:HikariCP连接泄漏检测阈值(调整为35分钟,匹配Jenkins构建轮询时长)
|
||||
- 优化:SSHJ底层日志屏蔽(Transport/SecureRandom等无业务价值日志降级为WARN)
|
||||
- 优化:服务器连接状态日志(提升连接成功日志为INFO,便于生产监控)
|
||||
- 优化:Liquibase配置(includeAll只扫描XML文件,避免SQL重复执行)
|
||||
- 新增:系统指标监控菜单(实时查看JVM、CPU、内存、线程、连接池等性能指标)
|
||||
- 新增:Actuator监控端点(threaddump/heapdump/env/loggers,支持动态调整日志级别)
|
||||
- 数据:新增用户lukuan及角色绑定(深圳部门/开发角色)
|
||||
',
|
||||
0, NULL, NULL, 0
|
||||
);
|
||||
@ -131,7 +131,7 @@ workflow.definition.not.published=工作流定义未发布
|
||||
workflow.definition.already.published=工作流定义已发布
|
||||
workflow.definition.cannot.delete=工作流定义已被使用,无法删除
|
||||
workflow.not.draft=只有草稿状态的工作流定义可以发布
|
||||
workflow.not.published=只有已发布状态的工作流定义可以禁用
|
||||
workflow.not.published=工作流未发布,请联系部署管理员进行工作流调整
|
||||
workflow.not.disabled=只有已禁用状态的工作流定义可以启用
|
||||
workflow.disabled=工作流已禁用
|
||||
workflow.invalid.status=工作流状态无效
|
||||
|
||||
@ -127,7 +127,7 @@ workflow.definition.not.published=Workflow definition not published
|
||||
workflow.definition.already.published=Workflow definition already published
|
||||
workflow.definition.cannot.delete=Workflow definition is in use and cannot be deleted
|
||||
workflow.not.draft=Only draft workflow definitions can be published
|
||||
workflow.not.published=Only published workflow definitions can be disabled
|
||||
workflow.not.published=Workflow not published, please contact deployment administrator for workflow adjustment
|
||||
workflow.not.disabled=Only disabled workflow definitions can be enabled
|
||||
workflow.disabled=Workflow is disabled
|
||||
workflow.invalid.status=Invalid workflow status
|
||||
|
||||
@ -127,7 +127,7 @@ workflow.definition.not.published=工作流定义未发布
|
||||
workflow.definition.already.published=工作流定义已发布
|
||||
workflow.definition.cannot.delete=工作流定义已被使用,无法删除
|
||||
workflow.not.draft=只有草稿状态的工作流定义可以发布
|
||||
workflow.not.published=只有已发布状态的工作流定义可以禁用
|
||||
workflow.not.published=工作流未发布,请联系部署管理员进行工作流调整
|
||||
workflow.not.disabled=只有已禁用状态的工作流定义可以启用
|
||||
workflow.disabled=工作流已禁用
|
||||
workflow.invalid.status=工作流状态无效
|
||||
|
||||
Loading…
Reference in New Issue
Block a user