fix(ocr): eliminate race window in runOrQueueSenderTraining by creating RUNNING row atomically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -176,12 +176,38 @@ class SenderModelServiceTest {
|
||||
verify(trainingRunRepository, never()).save(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void runOrQueueSenderTraining_createsRunningRow_atomically() {
|
||||
// RUNNING row must be created inside the same @Transactional boundary as the idle check,
|
||||
// eliminating the race window between the check and a separate triggerSenderTraining call.
|
||||
when(trainingRunRepository.existsByPersonIdAndStatus(personId, TrainingStatus.QUEUED)).thenReturn(false);
|
||||
when(trainingRunRepository.findFirstByStatus(TrainingStatus.RUNNING)).thenReturn(Optional.empty());
|
||||
when(blockRepository.countManualKurrentBlocksByPerson(personId)).thenReturn(120L);
|
||||
when(trainingRunRepository.save(any())).thenAnswer(inv -> {
|
||||
OcrTrainingRun r = inv.getArgument(0);
|
||||
if (r.getId() == null) r.setId(UUID.randomUUID());
|
||||
return r;
|
||||
});
|
||||
|
||||
boolean result = service.runOrQueueSenderTraining(personId, 120);
|
||||
|
||||
assertThat(result).isTrue();
|
||||
verify(trainingRunRepository).save(argThat(r ->
|
||||
r.getStatus() == TrainingStatus.RUNNING && personId.equals(r.getPersonId())));
|
||||
}
|
||||
|
||||
// ─── triggerSenderTraining — queue promotion ──────────────────────────────
|
||||
|
||||
@Test
|
||||
void triggerSenderTraining_promotesNextQueued_afterCompletion() throws Exception {
|
||||
UUID nextPersonId = UUID.randomUUID();
|
||||
|
||||
OcrTrainingRun runningRun = OcrTrainingRun.builder()
|
||||
.id(UUID.randomUUID()).status(TrainingStatus.RUNNING)
|
||||
.personId(personId).blockCount(10).documentCount(0)
|
||||
.modelName("sender_" + personId).build();
|
||||
when(trainingRunRepository.findFirstByPersonIdAndStatus(personId, TrainingStatus.RUNNING))
|
||||
.thenReturn(Optional.of(runningRun));
|
||||
when(blockRepository.countManualKurrentBlocksByPerson(personId)).thenReturn(10L);
|
||||
when(trainingRunRepository.save(any())).thenAnswer(inv -> {
|
||||
OcrTrainingRun r = inv.getArgument(0);
|
||||
|
||||
Reference in New Issue
Block a user