11package io .kafbat .ui .service ;
22
3+ import static org .apache .kafka .common .config .TopicConfig .CLEANUP_POLICY_CONFIG ;
34import static org .assertj .core .api .Assertions .assertThat ;
45import static org .mockito .ArgumentMatchers .any ;
56import static org .mockito .ArgumentMatchers .anyBoolean ;
67import static org .mockito .ArgumentMatchers .anyList ;
78import static org .mockito .ArgumentMatchers .isA ;
8- import static org .mockito .ArgumentMatchers .isNull ;
99import static org .mockito .Mockito .mock ;
1010import static org .mockito .Mockito .when ;
1111
1212import io .kafbat .ui .config .ClustersProperties ;
1313import io .kafbat .ui .controller .TopicsController ;
1414import io .kafbat .ui .mapper .ClusterMapper ;
1515import io .kafbat .ui .mapper .ClusterMapperImpl ;
16- import io .kafbat .ui .model .InternalLogDirStats ;
16+ import io .kafbat .ui .model .CleanupPolicy ;
1717import io .kafbat .ui .model .InternalPartition ;
1818import io .kafbat .ui .model .InternalPartitionsOffsets ;
1919import io .kafbat .ui .model .InternalTopic ;
2727import io .kafbat .ui .service .audit .AuditService ;
2828import io .kafbat .ui .service .rbac .AccessControlService ;
2929import io .kafbat .ui .util .AccessControlServiceMock ;
30- import java .util .ArrayList ;
3130import java .util .Comparator ;
3231import java .util .List ;
3332import java .util .Map ;
3736import java .util .function .Function ;
3837import java .util .stream .Collectors ;
3938import java .util .stream .IntStream ;
39+ import org .apache .kafka .clients .admin .ConfigEntry ;
4040import org .apache .kafka .clients .admin .TopicDescription ;
41+ import org .apache .kafka .common .TopicPartition ;
4142import org .apache .kafka .common .TopicPartitionInfo ;
4243import org .junit .jupiter .api .Test ;
43- import org .mockito .ArgumentMatchers ;
4444import org .mockito .Mockito ;
4545import reactor .core .publisher .Mono ;
4646
@@ -70,6 +70,20 @@ class TopicsServicePaginationTest {
7070 private void init (Map <String , InternalTopic > topicsInCache ) {
7171 KafkaCluster kafkaCluster = buildKafkaCluster (LOCAL_KAFKA_CLUSTER_NAME );
7272 statisticsCache .replace (kafkaCluster , Statistics .empty ());
73+
74+ Map <TopicPartition , InternalPartitionsOffsets .Offsets > offsets = topicsInCache .values ().stream ()
75+ .flatMap (t ->
76+ t .getPartitions ().values ().stream ()
77+ .map (p ->
78+ Map .entry (
79+ new TopicPartition (t .getName (), p .getPartition ()),
80+ new InternalPartitionsOffsets .Offsets (p .getOffsetMin (), p .getOffsetMax ())
81+ )
82+ )
83+ ).filter (e ->
84+ e .getValue ().getEarliest () != null && e .getValue ().getLatest () != null
85+ ).collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
86+
7387 statisticsCache .update (
7488 kafkaCluster ,
7589 topicsInCache .entrySet ().stream ().collect (
@@ -78,8 +92,11 @@ private void init(Map<String, InternalTopic> topicsInCache) {
7892 v -> toTopicDescription (v .getValue ())
7993 )
8094 ),
81- Map .of (),
82- new InternalPartitionsOffsets (Map .of ()),
95+ topicsInCache .entrySet ().stream ()
96+ .map (t ->
97+ Map .entry (t .getKey (), List .of (new ConfigEntry (CLEANUP_POLICY_CONFIG , "delete" )))
98+ ).collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue )),
99+ new InternalPartitionsOffsets (offsets ),
83100 clustersProperties
84101 );
85102 when (adminClientService .get (isA (KafkaCluster .class ))).thenReturn (Mono .just (reactiveAdminClient ));
@@ -318,4 +335,61 @@ void shouldListTopicsOrderedByPartitionsCount() {
318335 );
319336 }
320337
338+ @ Test
339+ void shouldListTopicsOrderedByMessagesCount () {
340+ Map <String , InternalTopic > internalTopics = IntStream .rangeClosed (1 , 100 ).boxed ()
341+ .map (i -> new TopicDescription (UUID .randomUUID ().toString (), false ,
342+ IntStream .range (0 , i )
343+ .mapToObj (p ->
344+ new TopicPartitionInfo (p , null , List .of (), List .of ()))
345+ .collect (Collectors .toList ())))
346+ .map (topicDescription ->
347+ InternalTopic .from (topicDescription , List .of (),
348+ new InternalPartitionsOffsets (
349+ topicDescription .partitions ().stream ()
350+ .map (p -> Map .entry (
351+ new TopicPartition (topicDescription .name (), p .partition ()),
352+ new InternalPartitionsOffsets .Offsets (0L , (long ) p .partition ())
353+ )).collect (Collectors .toMap (
354+ Map .Entry ::getKey ,
355+ Map .Entry ::getValue
356+ ))
357+ ),
358+ Metrics .empty (), null , null , "_" )
359+ .toBuilder ().cleanUpPolicy (CleanupPolicy .DELETE ).build ()
360+ ).collect (Collectors .toMap (InternalTopic ::getName , Function .identity ()));
361+
362+ init (internalTopics );
363+
364+ var topicsSortedAsc = topicsController
365+ .getTopics (LOCAL_KAFKA_CLUSTER_NAME , null , null , null ,
366+ null , TopicColumnsToSortDTO .MESSAGES_COUNT , null , null ).block ();
367+
368+ assertThat (topicsSortedAsc .getBody ().getPageCount ()).isEqualTo (4 );
369+ assertThat (topicsSortedAsc .getBody ().getTopics ()).hasSize (25 );
370+ assertThat (topicsSortedAsc .getBody ().getTopics ()).containsExactlyElementsOf (
371+ internalTopics .values ().stream ()
372+ .map (clusterMapper ::toTopic )
373+ .sorted (Comparator .comparing (
374+ (t ) -> t .getMessagesCount ().get ()
375+ ))
376+ .limit (25 )
377+ .collect (Collectors .toList ())
378+ );
379+
380+ var topicsSortedDesc = topicsController
381+ .getTopics (LOCAL_KAFKA_CLUSTER_NAME , null , null , null ,
382+ null , TopicColumnsToSortDTO .TOTAL_PARTITIONS , SortOrderDTO .DESC , null ).block ();
383+
384+ assertThat (topicsSortedDesc .getBody ().getPageCount ()).isEqualTo (4 );
385+ assertThat (topicsSortedDesc .getBody ().getTopics ()).hasSize (25 );
386+ assertThat (topicsSortedDesc .getBody ().getTopics ()).containsExactlyElementsOf (
387+ internalTopics .values ().stream ()
388+ .map (clusterMapper ::toTopic )
389+ .sorted (Comparator .comparing (TopicDTO ::getPartitionCount ).reversed ())
390+ .limit (25 )
391+ .collect (Collectors .toList ())
392+ );
393+ }
394+
321395}
0 commit comments