From db93713bacffb95e999cc87b5ef4023fcf58e333 Mon Sep 17 00:00:00 2001 From: Mukhiddin Yusupov <133661057+mukhiddin-yusuf@users.noreply.github.com> Date: Tue, 2 Jul 2024 19:37:13 +0500 Subject: [PATCH] fix(authority): Fix handling heading type change update event for authority with linked instance * fix(authority): Fix handling heading type change update event for authority with linked instance - do not hard delete authority when handling heading type change update event Closes: MODELINKS-242 --- NEWS.md | 1 + .../handler/DeleteAuthorityChangeHandler.java | 16 +++-- ...nstanceAuthorityLinkUpdateServiceTest.java | 32 ++++++++++ .../DeleteAuthorityChangeHandlerTest.java | 63 +++++++++++++++---- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/NEWS.md b/NEWS.md index c8955c4b..dbfca9b3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -65,6 +65,7 @@ * Add new error code to handle authority source file deletion after authority deletion ([MODELINKS-210](https://issues.folio.org/browse/MODELINKS-210)) * Fix authority record update and `updatedByUserId` field assignment ([MODELINKS-219](https://issues.folio.org/browse/MODELINKS-219)) * Fix saving of Authority file with empty Base URL when another Authority file with empty Base URL already exists ([MODELINKS-216](https://issues.folio.org/browse/MODELINKS-216)) +* Fix handling of authority heading type change update event ([MODELINKS-242](https://issues.folio.org/browse/MODELINKS-242)) ### Tech Dept * Create custom Mockito verifies for Hibernate entities ([MODELINKS-209](https://issues.folio.org/browse/MODELINKS-209)) diff --git a/src/main/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandler.java b/src/main/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandler.java index 1fa48080..b790eef5 100644 --- a/src/main/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandler.java +++ b/src/main/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandler.java @@ -1,9 +1,11 @@ package org.folio.entlinks.service.messaging.authority.handler; import static java.util.Collections.emptyList; +import static org.folio.entlinks.service.messaging.authority.model.AuthorityChangeType.DELETE; import java.util.List; import java.util.stream.Collectors; +import org.apache.commons.collections4.CollectionUtils; import org.folio.entlinks.config.properties.InstanceAuthorityChangeProperties; import org.folio.entlinks.domain.dto.LinksChangeEvent; import org.folio.entlinks.service.authority.AuthorityService; @@ -42,11 +44,17 @@ public List handle(List changes) { .toList(); var authorityIds = linksEvents.stream().map(LinksChangeEvent::getAuthorityId).collect(Collectors.toSet()); - var softDeleteAuthorityIds = changes.stream().map(AuthorityChangeHolder::getAuthorityId).toList(); + var softDeleteAuthorityIds = changes.stream() + .filter(change -> change.getChangeType().equals(DELETE)) + .map(AuthorityChangeHolder::getAuthorityId) + .toList(); + // delete the links linkingService.deleteByAuthorityIdIn(authorityIds); - // hard delete the authorities - authorityService.deleteByIds(softDeleteAuthorityIds); + if (CollectionUtils.isNotEmpty(softDeleteAuthorityIds)) { + // hard delete authorities + authorityService.deleteByIds(softDeleteAuthorityIds); + } return linksEvents; } @@ -57,7 +65,7 @@ public LinksChangeEvent.TypeEnum getReplyEventType() { @Override public AuthorityChangeType supportedAuthorityChangeType() { - return AuthorityChangeType.DELETE; + return DELETE; } } diff --git a/src/test/java/org/folio/entlinks/service/messaging/authority/InstanceAuthorityLinkUpdateServiceTest.java b/src/test/java/org/folio/entlinks/service/messaging/authority/InstanceAuthorityLinkUpdateServiceTest.java index 09a92807..4056cba3 100644 --- a/src/test/java/org/folio/entlinks/service/messaging/authority/InstanceAuthorityLinkUpdateServiceTest.java +++ b/src/test/java/org/folio/entlinks/service/messaging/authority/InstanceAuthorityLinkUpdateServiceTest.java @@ -175,6 +175,38 @@ void handleAuthoritiesChanges_positive_deleteEvent() { assertThat(messages.get(0).getType()).isEqualTo(LinksChangeEvent.TypeEnum.DELETE); } + @Test + void handleAuthoritiesChanges_positive_shouldHandleHeadingTypeChangeUpdateEventAndSendDeleteLinksChangeEvent() { + var id = UUID.randomUUID(); + final var authorityEvents = List.of( + new AuthorityDomainEvent( + id, + new AuthorityDto().naturalId("n12345").corporateName("Beatles"), + new AuthorityDto().naturalId("n12345").corporateNameTitle("Beatles mono"), + DomainEventType.UPDATE, + TENANT_ID) + ); + var changeEvent = new LinksChangeEvent().type(LinksChangeEvent.TypeEnum.DELETE); + when(linkingService.countLinksByAuthorityIds(Set.of(id))).thenReturn(Map.of(id, 1)); + when(deleteHandler.handle(changeHolderCaptor.capture())).thenReturn(List.of(changeEvent)); + when(folioExecutionContext.getTenantId()).thenReturn(TENANT_ID); + + service.handleAuthoritiesChanges(authorityEvents); + + verify(updateHandler).supportedAuthorityChangeType(); + verify(deleteHandler).supportedAuthorityChangeType(); + verifyNoMoreInteractions(updateHandler); + verify(eventProducer, times(1)).sendMessages(eventCaptor.capture()); + var changeHolders = changeHolderCaptor.getAllValues().stream().flatMap(Collection::stream).toList(); + assertThat(changeHolders) + .hasSize(1) + .extracting(AuthorityChangeHolder::getNumberOfLinks) + .containsExactlyInAnyOrder(1); + var messages = eventCaptor.getAllValues().stream().flatMap(Collection::stream).toList(); + assertThat(messages).hasSize(1); + assertThat(messages.get(0).getType()).isEqualTo(LinksChangeEvent.TypeEnum.DELETE); + } + @Test void handleAuthoritiesChanges_positive_updateEventOnConsortiumCentralTenant() { final var id = UUID.randomUUID(); diff --git a/src/test/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandlerTest.java b/src/test/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandlerTest.java index b5fc03b5..052a57ab 100644 --- a/src/test/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandlerTest.java +++ b/src/test/java/org/folio/entlinks/service/messaging/authority/handler/DeleteAuthorityChangeHandlerTest.java @@ -5,13 +5,16 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.groups.Tuple.tuple; import static org.folio.entlinks.domain.dto.LinksChangeEvent.TypeEnum; +import static org.folio.support.base.TestConstants.TENANT_ID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyCollection; import static org.mockito.ArgumentMatchers.anySet; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import java.util.Collections; @@ -19,10 +22,12 @@ import java.util.Set; import java.util.UUID; import org.folio.entlinks.config.properties.InstanceAuthorityChangeProperties; +import org.folio.entlinks.domain.dto.AuthorityDto; import org.folio.entlinks.domain.dto.ChangeTarget; import org.folio.entlinks.domain.dto.ChangeTargetLink; import org.folio.entlinks.domain.dto.LinksChangeEvent; import org.folio.entlinks.integration.dto.event.AuthorityDomainEvent; +import org.folio.entlinks.integration.dto.event.DomainEventType; import org.folio.entlinks.service.authority.AuthorityService; import org.folio.entlinks.service.links.InstanceAuthorityLinkingService; import org.folio.entlinks.service.messaging.authority.model.AuthorityChangeHolder; @@ -61,11 +66,18 @@ void supportedInventoryEventType_positive() { } @Test - void handle_positive() { - var eventIds = Set.of(UUID.randomUUID(), UUID.randomUUID()); - var events = eventIds.stream() - .map(uuid -> new AuthorityChangeHolder(new AuthorityDomainEvent(uuid), emptyMap(), emptyMap(), 1)) - .toList(); + void handle_positive_shouldHardDeleteAuthorityAndLinks() { + var id1 = UUID.randomUUID(); + var id2 = UUID.randomUUID(); + var authorityDto = new AuthorityDto().naturalId("n12345").personalName("name"); + var authorityDomainEvent1 = new AuthorityDomainEvent( + id1, authorityDto, authorityDto, DomainEventType.DELETE, TENANT_ID); + var authorityDomainEvent2 = new AuthorityDomainEvent( + id2, authorityDto, authorityDto, DomainEventType.DELETE, TENANT_ID); + var events = List.of( + new AuthorityChangeHolder(authorityDomainEvent1, emptyMap(), emptyMap(), 1), + new AuthorityChangeHolder(authorityDomainEvent2, emptyMap(), emptyMap(), 1) + ); var instanceId1 = UUID.randomUUID(); var instanceId2 = UUID.randomUUID(); var instanceId3 = UUID.randomUUID(); @@ -75,30 +87,59 @@ void handle_positive() { doNothing().when(linkingService).deleteByAuthorityIdIn(anySet()); when(properties.getNumPartitions()).thenReturn(1); - when(linkingService.getLinksByAuthorityId(eq(events.get(0).getAuthorityId()), any())).thenReturn( + when(linkingService.getLinksByAuthorityId(eq(id1), any())).thenReturn( new PageImpl<>(List.of(link1.toEntity(instanceId1)), Pageable.ofSize(1), 2) ).thenReturn( new PageImpl<>(List.of(link2.toEntity(instanceId2))) ); - when(linkingService.getLinksByAuthorityId(eq(events.get(1).getAuthorityId()), any())).thenReturn( + when(linkingService.getLinksByAuthorityId(eq(id2), any())).thenReturn( new PageImpl<>(List.of(link3.toEntity(instanceId3))) ); var actual = handler.handle(events); - verify(linkingService).deleteByAuthorityIdIn(eventIds); + verify(linkingService).deleteByAuthorityIdIn(Set.of(id1, id2)); + verify(linkingService, times(3)).getLinksByAuthorityId(any(UUID.class), any(Pageable.class)); assertThat(actual) .hasSize(3) .extracting(LinksChangeEvent::getAuthorityId, LinksChangeEvent::getType, LinksChangeEvent::getUpdateTargets) .contains( - tuple(events.get(0).getAuthorityId(), TypeEnum.DELETE, List.of(changeTarget(instanceId1, link1))), - tuple(events.get(0).getAuthorityId(), TypeEnum.DELETE, List.of(changeTarget(instanceId2, link2))), - tuple(events.get(1).getAuthorityId(), TypeEnum.DELETE, List.of(changeTarget(instanceId3, link3))) + tuple(id1, TypeEnum.DELETE, List.of(changeTarget(instanceId1, link1))), + tuple(id1, TypeEnum.DELETE, List.of(changeTarget(instanceId2, link2))), + tuple(id2, TypeEnum.DELETE, List.of(changeTarget(instanceId3, link3))) ); verify(authorityService).deleteByIds(anyCollection()); } + @Test + void handle_positive_shouldDeleteLinksOnlyOnHeadingTypeChangeUpdateEvent() { + var id = UUID.randomUUID(); + var authorityDomainEvent = new AuthorityDomainEvent( + id, + new AuthorityDto().naturalId("n12345").corporateName("Beatles"), + new AuthorityDto().naturalId("n12345").corporateNameTitle("Beatles mono"), + DomainEventType.UPDATE, + TENANT_ID); + var authorityEvents = List.of(new AuthorityChangeHolder(authorityDomainEvent, emptyMap(), emptyMap(), 1)); + var link = TestDataUtils.Link.of(1, 1); + var instanceId = UUID.randomUUID(); + doNothing().when(linkingService).deleteByAuthorityIdIn(Set.of(id)); + when(properties.getNumPartitions()).thenReturn(1); + when(linkingService.getLinksByAuthorityId(eq(id), any())).thenReturn( + new PageImpl<>(List.of(link.toEntity(instanceId)), Pageable.ofSize(1), 1)); + + var actual = handler.handle(authorityEvents); + + verify(linkingService).getLinksByAuthorityId(eq(id), any()); + verify(linkingService).deleteByAuthorityIdIn(Set.of(id)); + assertThat(actual) + .hasSize(1) + .extracting(LinksChangeEvent::getAuthorityId, LinksChangeEvent::getType, LinksChangeEvent::getUpdateTargets) + .contains(tuple(id, TypeEnum.DELETE, List.of(changeTarget(instanceId, link)))); + verifyNoInteractions(authorityService); + } + @Test void handle_positive_emptyEventList() { var actual = handler.handle(emptyList());