refactor(ocr): extract assertNoRunningTraining() to eliminate duplicate guard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,13 @@ public class OcrTrainingService {
|
|||||||
List<OcrTrainingRun> runs
|
List<OcrTrainingRun> runs
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
private void assertNoRunningTraining() {
|
||||||
|
if (trainingRunRepository.findFirstByStatus(TrainingStatus.RUNNING).isPresent()) {
|
||||||
|
throw DomainException.conflict(ErrorCode.TRAINING_ALREADY_RUNNING,
|
||||||
|
"A training run is already in progress");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Not safe for horizontal scaling: training reloads the Kraken model in-process on the
|
// Not safe for horizontal scaling: training reloads the Kraken model in-process on the
|
||||||
// Python OCR service after each run. The DB-level RUNNING constraint (V30 partial unique
|
// Python OCR service after each run. The DB-level RUNNING constraint (V30 partial unique
|
||||||
// index) prevents concurrent training API calls, but cannot prevent two OCR service replicas
|
// index) prevents concurrent training API calls, but cannot prevent two OCR service replicas
|
||||||
@@ -53,10 +60,7 @@ public class OcrTrainingService {
|
|||||||
// Short transaction: guard check + create RUNNING row, then commit immediately.
|
// Short transaction: guard check + create RUNNING row, then commit immediately.
|
||||||
// The DB connection is released before the OCR HTTP call, which can take several minutes.
|
// The DB connection is released before the OCR HTTP call, which can take several minutes.
|
||||||
OcrTrainingRun run = Objects.requireNonNull(txTemplate.execute(status -> {
|
OcrTrainingRun run = Objects.requireNonNull(txTemplate.execute(status -> {
|
||||||
if (trainingRunRepository.findFirstByStatus(TrainingStatus.RUNNING).isPresent()) {
|
assertNoRunningTraining();
|
||||||
throw DomainException.conflict(ErrorCode.TRAINING_ALREADY_RUNNING,
|
|
||||||
"A training run is already in progress");
|
|
||||||
}
|
|
||||||
|
|
||||||
var eligibleBlocks = trainingDataExportService.queryEligibleBlocks();
|
var eligibleBlocks = trainingDataExportService.queryEligibleBlocks();
|
||||||
if (eligibleBlocks.size() < 5) {
|
if (eligibleBlocks.size() < 5) {
|
||||||
@@ -120,10 +124,7 @@ public class OcrTrainingService {
|
|||||||
public OcrTrainingRun triggerSegTraining(UUID triggeredBy) {
|
public OcrTrainingRun triggerSegTraining(UUID triggeredBy) {
|
||||||
// Same pattern as triggerTraining: narrow transactions around DB writes only.
|
// Same pattern as triggerTraining: narrow transactions around DB writes only.
|
||||||
OcrTrainingRun run = Objects.requireNonNull(txTemplate.execute(status -> {
|
OcrTrainingRun run = Objects.requireNonNull(txTemplate.execute(status -> {
|
||||||
if (trainingRunRepository.findFirstByStatus(TrainingStatus.RUNNING).isPresent()) {
|
assertNoRunningTraining();
|
||||||
throw DomainException.conflict(ErrorCode.TRAINING_ALREADY_RUNNING,
|
|
||||||
"A training run is already in progress");
|
|
||||||
}
|
|
||||||
|
|
||||||
var segBlocks = segmentationTrainingExportService.querySegmentationBlocks();
|
var segBlocks = segmentationTrainingExportService.querySegmentationBlocks();
|
||||||
if (segBlocks.size() < 5) {
|
if (segBlocks.size() < 5) {
|
||||||
|
|||||||
Reference in New Issue
Block a user