perf(ocr): resolve person names in single batch query in getTrainingInfo

Replace the per-run getById loop with a single getAllById call on distinct
person IDs, eliminating the N+1 query when training history contains multiple
sender model runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-17 21:21:12 +02:00
parent 4aa477555d
commit 0d5f3f38d0
2 changed files with 40 additions and 9 deletions

View File

@@ -202,16 +202,15 @@ public class OcrTrainingService {
List<OcrTrainingRun> recentRuns = trainingRunRepository.findTop20ByOrderByCreatedAtDesc();
OcrTrainingRun lastRun = recentRuns.isEmpty() ? null : recentRuns.get(0);
List<UUID> distinctPersonIds = recentRuns.stream()
.map(OcrTrainingRun::getPersonId)
.filter(Objects::nonNull)
.distinct()
.collect(java.util.stream.Collectors.toList());
Map<String, String> personNames = new HashMap<>();
for (OcrTrainingRun run : recentRuns) {
if (run.getPersonId() != null && !personNames.containsKey(run.getPersonId().toString())) {
try {
personNames.put(run.getPersonId().toString(),
personService.getById(run.getPersonId()).getDisplayName());
} catch (Exception e) {
log.debug("Could not resolve display name for person {}: {}", run.getPersonId(), e.getMessage());
}
}
if (!distinctPersonIds.isEmpty()) {
personService.getAllById(distinctPersonIds)
.forEach(p -> personNames.put(p.getId().toString(), p.getDisplayName()));
}
return new TrainingInfoResponse(