增加生成后端服务代码。
This commit is contained in:
parent
07db17faf6
commit
d30614c857
@ -65,36 +65,126 @@ public class RepositoryBranchServiceImpl extends BaseServiceImpl<RepositoryBranc
|
||||
@Resource(name = "repositoryBranchExecutor")
|
||||
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 long RETRY_DELAY = 100L;
|
||||
|
||||
private static final int MAX_WEB_URL_LENGTH = 1000; // web_url 字段最大长度
|
||||
|
||||
/**
|
||||
* 批量保存分支(优化版)
|
||||
* 1. 分批保存,减少单次事务大小
|
||||
* 2. 单条记录失败不影响其他记录
|
||||
* 3. 支持乐观锁重试
|
||||
*/
|
||||
@Transactional
|
||||
public void saveBatch(List<RepositoryBranch> branches) {
|
||||
int retryCount = 0;
|
||||
while (retryCount < MAX_RETRIES) {
|
||||
try {
|
||||
if (branches == null || branches.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
int end = Math.min(i + BATCH_SIZE, branches.size());
|
||||
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) {
|
||||
// 乐观锁冲突,重试
|
||||
retryCount++;
|
||||
if (retryCount >= MAX_RETRIES) {
|
||||
throw e;
|
||||
}
|
||||
log.warn("Optimistic locking failure during batch save, retry attempt {}", retryCount);
|
||||
if (retryCount > MAX_RETRIES) {
|
||||
failureCount++;
|
||||
String errorMsg = String.format("%s (乐观锁冲突)", branch.getName());
|
||||
failedBranches.add(errorMsg);
|
||||
log.error("分支 {} 保存失败,乐观锁冲突重试 {} 次后仍失败", branch.getName(), MAX_RETRIES, e);
|
||||
} else {
|
||||
log.warn("分支 {} 乐观锁冲突,进行第 {} 次重试", branch.getName(), retryCount);
|
||||
try {
|
||||
Thread.sleep(RETRY_DELAY * retryCount);
|
||||
} catch (InterruptedException ie) {
|
||||
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 '最新提交时间',
|
||||
last_update_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',
|
||||
external_system_id BIGINT NOT NULL COMMENT '外部系统ID',
|
||||
repo_project_id BIGINT NOT NULL COMMENT 'GitLab的真实project_id',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user