fix(dashboard): bulk-load document titles in getActivity to avoid N+1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -124,12 +124,11 @@ public class DashboardService {
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
Map<UUID, String> titleCache = new HashMap<>();
|
Map<UUID, String> titleCache = new HashMap<>();
|
||||||
for (UUID docId : docIds) {
|
try {
|
||||||
try {
|
documentService.getDocumentsByIds(docIds)
|
||||||
titleCache.put(docId, documentService.getDocumentById(docId).getTitle());
|
.forEach(d -> titleCache.put(d.getId(), d.getTitle()));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
titleCache.put(docId, "");
|
log.warn("Activity: failed to bulk-load document titles", e);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows.stream().map(row -> {
|
return rows.stream().map(row -> {
|
||||||
|
|||||||
@@ -484,6 +484,10 @@ public class DocumentService {
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Document> getDocumentsByIds(List<UUID> ids) {
|
||||||
|
return documentRepository.findAllById(ids);
|
||||||
|
}
|
||||||
|
|
||||||
public List<Document> getDocumentsWithoutVersions() {
|
public List<Document> getDocumentsWithoutVersions() {
|
||||||
return documentRepository.findDocumentsWithoutVersions();
|
return documentRepository.findDocumentsWithoutVersions();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,16 @@ import org.raddatz.familienarchiv.service.DocumentService;
|
|||||||
import org.raddatz.familienarchiv.service.TranscriptionService;
|
import org.raddatz.familienarchiv.service.TranscriptionService;
|
||||||
import org.raddatz.familienarchiv.service.UserService;
|
import org.raddatz.familienarchiv.service.UserService;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.Instant;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyList;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
@@ -65,4 +68,40 @@ class DashboardServiceTest {
|
|||||||
assertThat(result.collaborators()).hasSize(1);
|
assertThat(result.collaborators()).hasSize(1);
|
||||||
assertThat(result.collaborators().get(0).name()).isEqualTo("Schmidt");
|
assertThat(result.collaborators().get(0).name()).isEqualTo("Schmidt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── getActivity bulk-load ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getActivity_loadsDocumentTitles_withoutPerRowLookup() {
|
||||||
|
UUID userId = UUID.randomUUID();
|
||||||
|
UUID docId = UUID.randomUUID();
|
||||||
|
|
||||||
|
ActivityFeedRow row = mockFeedRow(docId, "ANNOTATION_CREATED");
|
||||||
|
when(auditLogQueryService.findActivityFeed(userId, 5)).thenReturn(List.of(row, row));
|
||||||
|
|
||||||
|
Document doc = Document.builder()
|
||||||
|
.id(docId).title("Familienbrief").originalFilename("f.pdf")
|
||||||
|
.receivers(new HashSet<>())
|
||||||
|
.build();
|
||||||
|
when(documentService.getDocumentsByIds(List.of(docId))).thenReturn(List.of(doc));
|
||||||
|
|
||||||
|
List<ActivityFeedItemDTO> items = dashboardService.getActivity(userId, 5);
|
||||||
|
|
||||||
|
assertThat(items).hasSize(2);
|
||||||
|
assertThat(items.get(0).documentTitle()).isEqualTo("Familienbrief");
|
||||||
|
verify(documentService, never()).getDocumentById(docId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActivityFeedRow mockFeedRow(UUID docId, String kind) {
|
||||||
|
return new ActivityFeedRow() {
|
||||||
|
public String getKind() { return kind; }
|
||||||
|
public UUID getActorId() { return null; }
|
||||||
|
public String getActorInitials() { return ""; }
|
||||||
|
public String getActorColor() { return ""; }
|
||||||
|
public String getActorName() { return ""; }
|
||||||
|
public UUID getDocumentId() { return docId; }
|
||||||
|
public Instant getHappenedAt() { return Instant.now(); }
|
||||||
|
public boolean isYouMentioned() { return false; }
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user