Implement topics sorting (backend) (#1498)

* [ISSUE-1383]Create parameters of request for sorting topics. (backend)

* [ISSUE-1383]Create parameters of request for sorting topics. (backend)

Co-authored-by: Roman Zabaluev <rzabaluev@provectus.com>
This commit is contained in:
ValentinPrischepa 2022-01-31 02:38:56 -08:00 committed by GitHub
parent 540b8eb79b
commit 7cdcacf5d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 12 deletions

View file

@ -5,6 +5,7 @@ import com.provectus.kafka.ui.model.PartitionsIncreaseDTO;
import com.provectus.kafka.ui.model.PartitionsIncreaseResponseDTO;
import com.provectus.kafka.ui.model.ReplicationFactorChangeDTO;
import com.provectus.kafka.ui.model.ReplicationFactorChangeResponseDTO;
import com.provectus.kafka.ui.model.SortOrderDTO;
import com.provectus.kafka.ui.model.TopicColumnsToSortDTO;
import com.provectus.kafka.ui.model.TopicConfigDTO;
import com.provectus.kafka.ui.model.TopicCreationDTO;
@ -66,6 +67,7 @@ public class TopicsController extends AbstractController implements TopicsApi {
@Valid Boolean showInternal,
@Valid String search,
@Valid TopicColumnsToSortDTO orderBy,
@Valid SortOrderDTO sortOrder,
ServerWebExchange exchange) {
return topicsService
.getTopics(
@ -74,7 +76,8 @@ public class TopicsController extends AbstractController implements TopicsApi {
Optional.ofNullable(perPage),
Optional.ofNullable(showInternal),
Optional.ofNullable(search),
Optional.ofNullable(orderBy)
Optional.ofNullable(orderBy),
Optional.ofNullable(sortOrder)
).map(ResponseEntity::ok);
}

View file

@ -20,6 +20,7 @@ import com.provectus.kafka.ui.model.PartitionsIncreaseDTO;
import com.provectus.kafka.ui.model.PartitionsIncreaseResponseDTO;
import com.provectus.kafka.ui.model.ReplicationFactorChangeDTO;
import com.provectus.kafka.ui.model.ReplicationFactorChangeResponseDTO;
import com.provectus.kafka.ui.model.SortOrderDTO;
import com.provectus.kafka.ui.model.TopicColumnsToSortDTO;
import com.provectus.kafka.ui.model.TopicConfigDTO;
import com.provectus.kafka.ui.model.TopicCreationDTO;
@ -67,10 +68,11 @@ public class TopicsService {
Optional<Integer> nullablePerPage,
Optional<Boolean> showInternal,
Optional<String> search,
Optional<TopicColumnsToSortDTO> sortBy) {
Optional<TopicColumnsToSortDTO> sortBy,
Optional<SortOrderDTO> sortOrder) {
return adminClientService.get(cluster).flatMap(ac ->
new Pagination(ac, metricsCache.get(cluster))
.getPage(pageNum, nullablePerPage, showInternal, search, sortBy)
.getPage(pageNum, nullablePerPage, showInternal, search, sortBy, sortOrder)
.flatMap(page ->
loadTopics(cluster, page.getTopics())
.map(topics ->
@ -409,12 +411,15 @@ public class TopicsService {
Optional<Integer> nullablePerPage,
Optional<Boolean> showInternal,
Optional<String> search,
Optional<TopicColumnsToSortDTO> sortBy) {
Optional<TopicColumnsToSortDTO> sortBy,
Optional<SortOrderDTO> sortOrder) {
return geTopicsForPagination()
.map(paginatingTopics -> {
Predicate<Integer> positiveInt = i -> i > 0;
int perPage = nullablePerPage.filter(positiveInt).orElse(DEFAULT_PAGE_SIZE);
var topicsToSkip = (pageNum.filter(positiveInt).orElse(1) - 1) * perPage;
var comparator = sortOrder.isEmpty() || !sortOrder.get().equals(SortOrderDTO.DESC)
? getComparatorForTopic(sortBy) : getComparatorForTopic(sortBy).reversed();
List<InternalTopic> topics = paginatingTopics.stream()
.filter(topic -> !topic.isInternal()
|| showInternal.map(i -> topic.isInternal() == i).orElse(true))
@ -422,7 +427,7 @@ public class TopicsService {
search
.map(s -> StringUtils.containsIgnoreCase(topic.getName(), s))
.orElse(true))
.sorted(getComparatorForTopic(sortBy))
.sorted(comparator)
.collect(toList());
var totalPages = (topics.size() / perPage)
+ (topics.size() % perPage == 0 ? 0 : 1);

View file

@ -4,8 +4,10 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.provectus.kafka.ui.model.SortOrderDTO;
import com.provectus.kafka.ui.model.TopicColumnsToSortDTO;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -46,12 +48,35 @@ class TopicsServicePaginationTest {
var topics = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty()).block();
Optional.empty(), Optional.empty(), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(25);
assertThat(topics.getTopics()).isSorted();
}
@Test
public void shouldListFirst25TopicsSortedByNameDescendingOrder() {
var topicDescriptions = IntStream.rangeClosed(1, 100).boxed()
.map(Objects::toString)
.map(name -> new TopicDescription(name, false, List.of()))
.collect(Collectors.toList());
init(topicDescriptions);
var topics = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.of(TopicColumnsToSortDTO.NAME), Optional.of(SortOrderDTO.DESC)).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(25);
assertThat(topics.getTopics()).isSortedAccordingTo(Comparator.reverseOrder());
assertThat(topics.getTopics()).containsExactlyElementsOf(
topicDescriptions.stream()
.map(TopicDescription::name)
.sorted(Comparator.reverseOrder())
.limit(25)
.collect(Collectors.toList())
);
}
@Test
public void shouldCalculateCorrectPageCountForNonDivisiblePageSize() {
init(
@ -62,7 +87,7 @@ class TopicsServicePaginationTest {
);
var topics = pagination.getPage(Optional.of(4), Optional.of(33),
Optional.empty(), Optional.empty(), Optional.empty()).block();
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(1)
.first().isEqualTo("99");
@ -78,7 +103,7 @@ class TopicsServicePaginationTest {
);
var topics = pagination.getPage(Optional.of(0), Optional.of(-1),
Optional.empty(), Optional.empty(), Optional.empty()).block();
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(25);
assertThat(topics.getTopics()).isSorted();
@ -95,7 +120,7 @@ class TopicsServicePaginationTest {
var topics = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.of(true),
Optional.empty(), Optional.empty()).block();
Optional.empty(), Optional.empty(), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(25);
assertThat(topics.getTopics()).isSorted();
@ -113,7 +138,7 @@ class TopicsServicePaginationTest {
var topics = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.of(true),
Optional.empty(), Optional.empty()).block();
Optional.empty(), Optional.empty(), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(25);
assertThat(topics.getTopics()).isSorted();
@ -131,7 +156,7 @@ class TopicsServicePaginationTest {
var topics = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.of("1"), Optional.empty()).block();
Optional.of("1"), Optional.empty(), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(1);
assertThat(topics.getTopics()).hasSize(20);
assertThat(topics.getTopics()).isSorted();
@ -151,7 +176,7 @@ class TopicsServicePaginationTest {
var topics = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.of(TopicColumnsToSortDTO.TOTAL_PARTITIONS)).block();
Optional.empty(), Optional.of(TopicColumnsToSortDTO.TOTAL_PARTITIONS), Optional.empty()).block();
assertThat(topics.getTotalPages()).isEqualTo(4);
assertThat(topics.getTopics()).hasSize(25);
assertThat(topics.getTopics()).containsExactlyElementsOf(
@ -159,6 +184,18 @@ class TopicsServicePaginationTest {
.map(TopicDescription::name)
.limit(25)
.collect(Collectors.toList()));
var topicsSortedDesc = pagination.getPage(
Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.of(TopicColumnsToSortDTO.TOTAL_PARTITIONS), Optional.of(SortOrderDTO.DESC)).block();
assertThat(topicsSortedDesc.getTotalPages()).isEqualTo(4);
assertThat(topicsSortedDesc.getTopics()).hasSize(25);
assertThat(topicsSortedDesc.getTopics()).containsExactlyElementsOf(
topicDescriptions.stream()
.sorted((a, b) -> b.partitions().size() - a.partitions().size())
.map(TopicDescription::name)
.limit(25)
.collect(Collectors.toList()));
}
}

View file

@ -295,6 +295,11 @@ paths:
required: false
schema:
$ref: '#/components/schemas/TopicColumnsToSort'
- name: sortOrder
in: query
required: false
schema:
$ref: '#/components/schemas/SortOrder'
responses:
200:
description: OK
@ -1729,6 +1734,12 @@ components:
- TOTAL_PARTITIONS
- REPLICATION_FACTOR
SortOrder:
type: string
enum:
- ASC
- DESC
Topic:
type: object
properties: