diff --git a/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/RocketChatService.java b/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/RocketChatService.java index 5f9a36db0..446adaf72 100644 --- a/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/RocketChatService.java +++ b/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/RocketChatService.java @@ -1,10 +1,12 @@ package de.caritas.cob.userservice.api.adapters.rocketchat; import static de.caritas.cob.userservice.api.helper.CustomLocalDateTime.nowInUtc; +import static java.util.Arrays.asList; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import static org.apache.commons.lang3.ArrayUtils.isNotEmpty; +import com.google.common.collect.Lists; import com.mongodb.DBObject; import com.mongodb.QueryBuilder; import com.mongodb.client.MongoClient; @@ -59,7 +61,6 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -132,6 +133,7 @@ public class RocketChatService implements MessageClient { private static final String USERS_LIST_ERROR_MESSAGE = "Could not get users list from Rocket.Chat"; private static final String USER_LIST_GET_FIELD_SELECTION = "{\"_id\":1}"; + private static final Integer PAGE_SIZE = 100; private final LocalDateTime localDateTime1900 = LocalDateTime.of(1900, 1, 1, 0, 0); private final LocalDateTime localDateTimeFuture = nowInUtc().plusYears(1L); @@ -809,7 +811,7 @@ public List getMembersOfGroup(String rcGroupId) } if (response.getStatusCode() == HttpStatus.OK && nonNull(response.getBody())) { - return Arrays.asList(response.getBody().getMembers()); + return asList(response.getBody().getMembers()); } else { var error = "Could not get Rocket.Chat group members for room id %s"; throw new RocketChatGetGroupMembersException(String.format(error, rcGroupId)); @@ -908,7 +910,7 @@ public List getSubscriptionsOfUser( } if (response.getStatusCode() == HttpStatus.OK && nonNull(response.getBody())) { - return Arrays.asList(response.getBody().getUpdate()); + return asList(response.getBody().getUpdate()); } else { var error = "Could not get Rocket.Chat subscriptions for user id %s"; throw new InternalServerErrorException(error, LogService::logRocketChatError); @@ -967,7 +969,7 @@ public List getRoomsOfUser(RocketChatCredentials rocketChatCrede } if (response.getStatusCode() == HttpStatus.OK && nonNull(response.getBody())) { - return Arrays.asList(response.getBody().getUpdate()); + return asList(response.getBody().getUpdate()); } else { var error = String.format(CHAT_ROOM_ERROR_MESSAGE, rocketChatCredentials.getRocketChatUserId()); @@ -1188,28 +1190,72 @@ public List fetchAllInactivePrivateGroupsSinceGivenDate( private List getGroupsListAll(DBObject mongoDbQuery) throws RocketChatGetGroupsListAllException { - ResponseEntity response; try { var technicalUser = rcCredentialHelper.getTechnicalUser(); var header = getStandardHttpHeaders(technicalUser); HttpEntity request = new HttpEntity<>(header); - var url = rocketChatConfig.getApiUrl(ENDPOINT_GROUP_LIST) + "?query={query}"; - response = - restTemplate.exchange( - url, - HttpMethod.GET, - request, - GroupsListAllResponseDTO.class, - mongoDbQuery.toString()); + + return getGroupListAllCombiningPages(mongoDbQuery, request); } catch (Exception ex) { + log.error("Rocket.Chat Error: Could not get Rocket.Chat groups list all. Reason: ", ex); throw new RocketChatGetGroupsListAllException(GROUPS_LIST_ALL_ERROR_MESSAGE, ex); } + } - if (response.getStatusCode() == HttpStatus.OK && nonNull(response.getBody())) { - return Arrays.asList(response.getBody().getGroups()); - } else { + private List getGroupListAllCombiningPages( + DBObject mongoDbQuery, HttpEntity request) + throws RocketChatGetGroupsListAllException { + List result = Lists.newArrayList(); + int currentOffset = 0; + var pageResponse = + getGroupsListAllResponseDTOResponseEntityForCurrentOffset( + mongoDbQuery, request, currentOffset); + + var totalResultSize = 0; + if (isResponseSuccessful(pageResponse)) { + totalResultSize = pageResponse.getBody().getTotal(); + } + + while (isResponseSuccessful(pageResponse) && currentOffset < totalResultSize) { + result.addAll(asList(pageResponse.getBody().getGroups())); + currentOffset += PAGE_SIZE; + pageResponse = + getGroupsListAllResponseDTOResponseEntityForCurrentOffset( + mongoDbQuery, request, currentOffset); + } + if (pageResponse.getStatusCode() != HttpStatus.OK || isNull(pageResponse.getBody())) { + log.error( + "Could not get Rocket.Chat groups list all. Reason {} {}. Url {}", + pageResponse.getStatusCode(), + pageResponse.getBody(), + getGroupAllPaginatedUrl(currentOffset)); throw new RocketChatGetGroupsListAllException(GROUPS_LIST_ALL_ERROR_MESSAGE); } + + return result; + } + + private boolean isResponseSuccessful(ResponseEntity pageResponse) { + return pageResponse.getStatusCode() == HttpStatus.OK && nonNull(pageResponse.getBody()); + } + + private ResponseEntity + getGroupsListAllResponseDTOResponseEntityForCurrentOffset( + DBObject mongoDbQuery, HttpEntity request, int currentOffset) { + ResponseEntity response; + var url = getGroupAllPaginatedUrl(currentOffset); + response = + restTemplate.exchange( + url, HttpMethod.GET, request, GroupsListAllResponseDTO.class, mongoDbQuery.toString()); + return response; + } + + private String getGroupAllPaginatedUrl(int currentOffset) { + return rocketChatConfig.getApiUrl(ENDPOINT_GROUP_LIST) + + "?query={query}&offset=" + + currentOffset + + "&count=" + + PAGE_SIZE; } /** diff --git a/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/dto/group/GroupsListAllResponseDTO.java b/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/dto/group/GroupsListAllResponseDTO.java index 9d44da486..52f46e867 100644 --- a/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/dto/group/GroupsListAllResponseDTO.java +++ b/src/main/java/de/caritas/cob/userservice/api/adapters/rocketchat/dto/group/GroupsListAllResponseDTO.java @@ -18,4 +18,8 @@ public class GroupsListAllResponseDTO { @JsonProperty("groups") private GroupDTO[] groups; + + private Integer offset; + private Integer count; + private Integer total; } diff --git a/src/test/java/de/caritas/cob/userservice/api/service/RocketChatServiceTest.java b/src/test/java/de/caritas/cob/userservice/api/service/RocketChatServiceTest.java index 7c846ec89..f04954fef 100644 --- a/src/test/java/de/caritas/cob/userservice/api/service/RocketChatServiceTest.java +++ b/src/test/java/de/caritas/cob/userservice/api/service/RocketChatServiceTest.java @@ -165,9 +165,16 @@ public class RocketChatServiceTest { new UsersListReponseDTO( new RocketChatUserDTO[] {ROCKET_CHAT_USER_DTO, ROCKET_CHAT_USER_DTO_2}); private final GroupsListAllResponseDTO GROUPS_LIST_ALL_RESPONSE_DTO_EMPTY = - new GroupsListAllResponseDTO(new GroupDTO[0]); + new GroupsListAllResponseDTO(new GroupDTO[0], 1, 0, 0); private final GroupsListAllResponseDTO GROUPS_LIST_ALL_RESPONSE_DTO = - new GroupsListAllResponseDTO(new GroupDTO[] {GROUP_DTO, GROUP_DTO_2}); + new GroupsListAllResponseDTO(new GroupDTO[] {GROUP_DTO, GROUP_DTO_2}, 0, 2, 10); + + private final GroupsListAllResponseDTO GROUPS_LIST_ALL_RESPONSE_DTO_PAGINATED = + new GroupsListAllResponseDTO(new GroupDTO[] {GROUP_DTO, GROUP_DTO_2}, 0, 100, 1000); + + private final GroupsListAllResponseDTO + GROUPS_LIST_ALL_RESPONSE_DTO_PAGINATED_WITH_TOTAL_ZERO_ELEMENTS = + new GroupsListAllResponseDTO(new GroupDTO[] {GROUP_DTO, GROUP_DTO_2}, 0, 0, 0); private final LocalDateTime DATETIME_OLDEST = nowInUtc(); private final LocalDateTime DATETIME_LATEST = nowInUtc(); private final String PASSWORD = "password"; @@ -738,7 +745,7 @@ public void removeAllMessages_Should_NotThrowException_WhenRemoveMessagesSucceed List result = rocketChatService.getStandardMembersOfGroup(GROUP_ID); assertEquals(1, result.size()); - assertEquals(result.get(0).get_id(), "a"); + assertEquals("a", result.get(0).get_id()); } /** Method: getUserInfo */ @@ -1096,6 +1103,68 @@ public void fetchAllInactivePrivateGroupsSinceGivenDate_Should_UseCorrectMongoQu this.rocketChatService.fetchAllInactivePrivateGroupsSinceGivenDate(dateToCheck); + String correctMongoQuery = + "{\"lm\": {\"$lt\": {\"$date\": \"2021-01-01T00:00:00.000Z\"}}," + + " \"$and\": [{\"t\": \"p\"}]}"; + verify(restTemplate, times(2)) + .exchange( + anyString(), + eq(HttpMethod.GET), + any(), + eq(GroupsListAllResponseDTO.class), + eq(correctMongoQuery)); + } + + @Test + public void + fetchAllInactivePrivateGroupsSinceGivenDate_Should_CallRocketChatApiMultipleTimes_When_ResultIsPaginated() + throws RocketChatUserNotInitializedException, RocketChatGetGroupsListAllException { + + LocalDateTime dateToCheck = LocalDateTime.of(2021, 1, 1, 0, 0, 0); + + when(rcCredentialsHelper.getTechnicalUser()).thenReturn(RC_CREDENTIALS_TECHNICAL_A); + when(restTemplate.exchange( + anyString(), + eq(HttpMethod.GET), + any(), + eq(GroupsListAllResponseDTO.class), + anyString())) + .thenReturn(new ResponseEntity<>(GROUPS_LIST_ALL_RESPONSE_DTO_PAGINATED, HttpStatus.OK)); + + this.rocketChatService.fetchAllInactivePrivateGroupsSinceGivenDate(dateToCheck); + + String correctMongoQuery = + "{\"lm\": {\"$lt\": {\"$date\": \"2021-01-01T00:00:00.000Z\"}}," + + " \"$and\": [{\"t\": \"p\"}]}"; + verify(restTemplate, times(11)) + .exchange( + anyString(), + eq(HttpMethod.GET), + any(), + eq(GroupsListAllResponseDTO.class), + eq(correctMongoQuery)); + } + + @Test + public void + fetchAllInactivePrivateGroupsSinceGivenDate_Should_CallRocketChatApiOnlyOnce_When_ResponseContainsTotalOfZeroElements() + throws RocketChatUserNotInitializedException, RocketChatGetGroupsListAllException { + + LocalDateTime dateToCheck = LocalDateTime.of(2021, 1, 1, 0, 0, 0); + + when(rcCredentialsHelper.getTechnicalUser()).thenReturn(RC_CREDENTIALS_TECHNICAL_A); + when(restTemplate.exchange( + anyString(), + eq(HttpMethod.GET), + any(), + eq(GroupsListAllResponseDTO.class), + anyString())) + .thenReturn( + new ResponseEntity<>( + GROUPS_LIST_ALL_RESPONSE_DTO_PAGINATED_WITH_TOTAL_ZERO_ELEMENTS, HttpStatus.OK)); + + this.rocketChatService.fetchAllInactivePrivateGroupsSinceGivenDate(dateToCheck); + String correctMongoQuery = "{\"lm\": {\"$lt\": {\"$date\": \"2021-01-01T00:00:00.000Z\"}}," + " \"$and\": [{\"t\": \"p\"}]}";