增加生成后端服务代码。
This commit is contained in:
parent
07db17faf6
commit
d30614c857
@ -65,36 +65,126 @@ public class RepositoryBranchServiceImpl extends BaseServiceImpl<RepositoryBranc
|
|||||||
@Resource(name = "repositoryBranchExecutor")
|
@Resource(name = "repositoryBranchExecutor")
|
||||||
private ThreadPoolTaskExecutor executor;
|
private ThreadPoolTaskExecutor executor;
|
||||||
|
|
||||||
private static final int BATCH_SIZE = 100;
|
private static final int BATCH_SIZE = 50; // 减小批次大小,提高容错性
|
||||||
|
|
||||||
private static final int MAX_RETRIES = 3;
|
private static final int MAX_RETRIES = 3;
|
||||||
|
|
||||||
private static final long RETRY_DELAY = 100L;
|
private static final long RETRY_DELAY = 100L;
|
||||||
|
|
||||||
|
private static final int MAX_WEB_URL_LENGTH = 1000; // web_url 字段最大长度
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存分支(优化版)
|
||||||
|
* 1. 分批保存,减少单次事务大小
|
||||||
|
* 2. 单条记录失败不影响其他记录
|
||||||
|
* 3. 支持乐观锁重试
|
||||||
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public void saveBatch(List<RepositoryBranch> branches) {
|
public void saveBatch(List<RepositoryBranch> branches) {
|
||||||
int retryCount = 0;
|
if (branches == null || branches.isEmpty()) {
|
||||||
while (retryCount < MAX_RETRIES) {
|
return;
|
||||||
try {
|
}
|
||||||
|
|
||||||
|
log.info("开始批量保存 {} 条分支记录", branches.size());
|
||||||
|
int successCount = 0;
|
||||||
|
int failureCount = 0;
|
||||||
|
List<String> failedBranches = new ArrayList<>();
|
||||||
|
|
||||||
|
// 分批处理
|
||||||
for (int i = 0; i < branches.size(); i += BATCH_SIZE) {
|
for (int i = 0; i < branches.size(); i += BATCH_SIZE) {
|
||||||
int end = Math.min(i + BATCH_SIZE, branches.size());
|
int end = Math.min(i + BATCH_SIZE, branches.size());
|
||||||
List<RepositoryBranch> batch = branches.subList(i, end);
|
List<RepositoryBranch> batch = branches.subList(i, end);
|
||||||
repositoryBranchRepository.saveAll(batch);
|
|
||||||
|
// 批次内逐条保存,避免一条失败导致整批失败
|
||||||
|
for (RepositoryBranch branch : batch) {
|
||||||
|
int retryCount = 0;
|
||||||
|
boolean saved = false;
|
||||||
|
|
||||||
|
while (retryCount <= MAX_RETRIES && !saved) {
|
||||||
|
try {
|
||||||
|
// 数据清洗:截断过长的字段
|
||||||
|
sanitizeBranchData(branch);
|
||||||
|
|
||||||
|
// 保存单条记录
|
||||||
|
repositoryBranchRepository.save(branch);
|
||||||
|
successCount++;
|
||||||
|
saved = true;
|
||||||
|
|
||||||
|
if (retryCount > 0) {
|
||||||
|
log.info("分支 {} 重试第 {} 次成功", branch.getName(), retryCount);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
} catch (ObjectOptimisticLockingFailureException e) {
|
} catch (ObjectOptimisticLockingFailureException e) {
|
||||||
|
// 乐观锁冲突,重试
|
||||||
retryCount++;
|
retryCount++;
|
||||||
if (retryCount >= MAX_RETRIES) {
|
if (retryCount > MAX_RETRIES) {
|
||||||
throw e;
|
failureCount++;
|
||||||
}
|
String errorMsg = String.format("%s (乐观锁冲突)", branch.getName());
|
||||||
log.warn("Optimistic locking failure during batch save, retry attempt {}", retryCount);
|
failedBranches.add(errorMsg);
|
||||||
|
log.error("分支 {} 保存失败,乐观锁冲突重试 {} 次后仍失败", branch.getName(), MAX_RETRIES, e);
|
||||||
|
} else {
|
||||||
|
log.warn("分支 {} 乐观锁冲突,进行第 {} 次重试", branch.getName(), retryCount);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(RETRY_DELAY * retryCount);
|
Thread.sleep(RETRY_DELAY * retryCount);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
throw new RuntimeException("Interrupted during retry delay", ie);
|
log.error("重试延迟被中断", ie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 其他异常(如数据过长、约束冲突等),记录日志并跳过
|
||||||
|
failureCount++;
|
||||||
|
String errorMsg = String.format("%s (%s)", branch.getName(), e.getMessage());
|
||||||
|
failedBranches.add(errorMsg);
|
||||||
|
log.error("分支 {} 保存失败: {}, webUrl长度={}",
|
||||||
|
branch.getName(),
|
||||||
|
e.getMessage(),
|
||||||
|
branch.getWebUrl() != null ? branch.getWebUrl().length() : 0,
|
||||||
|
e);
|
||||||
|
break; // 非乐观锁异常不重试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("批次 [{}-{}] 保存完成,成功: {}, 失败: {}",
|
||||||
|
i, end - 1, successCount, failureCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 汇总结果
|
||||||
|
log.info("批量保存完成 - 总数: {}, 成功: {}, 失败: {}",
|
||||||
|
branches.size(), successCount, failureCount);
|
||||||
|
|
||||||
|
if (!failedBranches.isEmpty()) {
|
||||||
|
log.warn("保存失败的分支列表(前10条): {}",
|
||||||
|
failedBranches.stream().limit(10).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果全部失败,抛出异常
|
||||||
|
if (failureCount == branches.size() && branches.size() > 0) {
|
||||||
|
throw new BusinessException(ResponseCode.REPOSITORY_BRANCH_SYNC_FAILED,
|
||||||
|
new Object[]{"所有分支保存失败"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据清洗:截断过长的字段,避免数据库插入失败
|
||||||
|
*/
|
||||||
|
private void sanitizeBranchData(RepositoryBranch branch) {
|
||||||
|
// 截断 web_url
|
||||||
|
if (branch.getWebUrl() != null && branch.getWebUrl().length() > MAX_WEB_URL_LENGTH) {
|
||||||
|
String original = branch.getWebUrl();
|
||||||
|
branch.setWebUrl(original.substring(0, MAX_WEB_URL_LENGTH));
|
||||||
|
log.warn("分支 {} 的 web_url 超长({}字符),已截断至 {} 字符",
|
||||||
|
branch.getName(), original.length(), MAX_WEB_URL_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 截断 commit_message(TEXT 类型通常足够大,但防御性处理)
|
||||||
|
if (branch.getCommitMessage() != null && branch.getCommitMessage().length() > 5000) {
|
||||||
|
branch.setCommitMessage(branch.getCommitMessage().substring(0, 5000) + "...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 截断 commit_author
|
||||||
|
if (branch.getCommitAuthor() != null && branch.getCommitAuthor().length() > 100) {
|
||||||
|
branch.setCommitAuthor(branch.getCommitAuthor().substring(0, 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -353,7 +353,7 @@ CREATE TABLE deploy_repo_branch
|
|||||||
commit_date DATETIME(6) NULL COMMENT '最新提交时间',
|
commit_date DATETIME(6) NULL COMMENT '最新提交时间',
|
||||||
last_update_time DATETIME(6) NULL COMMENT '分支最后更新时间',
|
last_update_time DATETIME(6) NULL COMMENT '分支最后更新时间',
|
||||||
last_commit_time DATETIME(6) NULL COMMENT '分支最后提交时间',
|
last_commit_time DATETIME(6) NULL COMMENT '分支最后提交时间',
|
||||||
web_url VARCHAR(255) NULL COMMENT '网页URL',
|
web_url VARCHAR(1000) NULL COMMENT '网页URL',
|
||||||
project_id BIGINT NOT NULL COMMENT '所属项目ID',
|
project_id BIGINT NOT NULL COMMENT '所属项目ID',
|
||||||
external_system_id BIGINT NOT NULL COMMENT '外部系统ID',
|
external_system_id BIGINT NOT NULL COMMENT '外部系统ID',
|
||||||
repo_project_id BIGINT NOT NULL COMMENT 'GitLab的真实project_id',
|
repo_project_id BIGINT NOT NULL COMMENT 'GitLab的真实project_id',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user