You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

53 lines
2.5 KiB

package com.mydreamjob.resume;
import com.mydreamjob.candidatescore.refresh.CandidateScoringRefreshRequestService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* 简历版本写入工作单元:每个"计算版本号 + 插入"运行在独立事务(REQUIRES_NEW)。
*
* <p>原因:唯一键冲突(uk_resume_versions_user_no)会把 Hibernate 事务标记为 rollback-only,
* 在同一事务内重试必然回滚。独立事务保证单次冲突只回滚自身,外层可安全重试。
*/
@Component
@RequiredArgsConstructor
public class ResumeVersionWriter {
private final ResumeVersionRepository resumeVersionRepository;
/**
* R01-D4-2 F3:刷新登记必须与版本行在同一提交边界。
*
* <p>版本行由本组件的 {@code REQUIRES_NEW} 事务独立提交(这是既有的并发冲突重试防护,
* 不能移除)。若登记留在外层事务,外层在提交阶段失败就会出现"版本行已落库、刷新信号
* 丢失"。把登记放进本事务后,二者要么一起提交、要么一起回滚。</p>
*/
private final CandidateScoringRefreshRequestService scoringRefreshRequestService;
/** 计算用户下一个版本号(max+1)并插入;并发冲突抛 DataIntegrityViolationException */
@Transactional(propagation = Propagation.REQUIRES_NEW)
public ResumeVersion saveNewVersion(Long userId, String name, String storagePath,
String fileName, String contentType, long fileSize) {
Integer maxNo = resumeVersionRepository.findMaxVersionNo(userId);
int versionNo = (maxNo == null ? 0 : maxNo) + 1;
ResumeVersion version = ResumeVersion.builder()
.userId(userId)
.name(name)
.versionNo(versionNo)
.fileStoragePath(storagePath)
.fileName(fileName)
.contentType(contentType)
.fileSize(fileSize)
.defaultKey(null)
.status(ResumeVersion.STATUS_ACTIVE)
.build();
ResumeVersion saved = resumeVersionRepository.save(version);
// R01-D4-2 F3:与版本行同事务登记(RESUME 版本数/最近更新影响 GROWTH 维度)。
scoringRefreshRequestService.requestRefresh(userId, LocalDateTime.now());
return saved;
}
}