Selaa lähdekoodia

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>
ValentinPrischepa 3 vuotta sitten
vanhempi
commit
7cdcacf5d5

+ 4 - 1
kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/TopicsController.java

@@ -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);
   }
 

+ 9 - 4
kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/TopicsService.java

@@ -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);

+ 44 - 7
kafka-ui-api/src/test/java/com/provectus/kafka/ui/service/TopicsServicePaginationTest.java

@@ -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()));
   }
 
 }

+ 11 - 0
kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml

@@ -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: