Skip to content

Commit c7e7710

Browse files
authored
Merge pull request #102 from amosproj/feature/sprint-06-integration
sprint-06: integration
2 parents 55a499b + ff14ce5 commit c7e7710

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1154
-592
lines changed

README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,28 @@ We want to achieve this by structuring our UI according to the topology of Apach
1212
* Node.js Version **20.0.0** or higher
1313
* Docker Desktop
1414

15-
## Backend
15+
## Backend and Pulsar instance
1616

17-
First start Docker Desktop and create the pulsar setup from the root-directory with:
17+
First, build the application JAR from the `backend` directory with:
1818

19-
```docker-compose up -d```
19+
```./mvnw package -DskipTests```
2020

21-
Then start the application from the `backend` directory with:
2221

23-
```./mvnw spring-boot:run```
22+
Then, start Docker Desktop and create the pulsar setup from the root-directory with:
23+
24+
```docker-compose --profile demodata --profile backend up --build```
25+
26+
Notes:
27+
* `--build` is needed for the first startup, or when the demodata docker images are changed
28+
* `--profile demodata` is needed when you want to create the demo topology and start the demo producers & consumers, that will continuously send and receive messages
29+
* `--profile backend` is needed when you want to start the backend via the docker-compose setup. See below for starting it manually.
2430

25-
After the start, all old topics are automatically removed from the Pulsar instance and some new topics, messages and
26-
consumers are added.
31+
### Starting the backend separately
32+
33+
If you want to start the backend individually (e.g. during development), simply omit the `--profile backend` from the docker-compose command.
34+
Instead, start the application from the `backend` directory with:
35+
36+
```./mvnw spring-boot:run```
2737

2838
### Tests
2939

backend/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM --platform=linux/amd64 openjdk:17-jdk-alpine
2+
COPY target/apachepulsarui-0.0.1-SNAPSHOT.jar apachepulsarui.jar
3+
ENTRYPOINT ["java","-jar","/apachepulsarui.jar"]

backend/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@
9595
<dependency>
9696
<groupId>org.apache.pulsar</groupId>
9797
<artifactId>pulsar-client</artifactId>
98-
<version>2.11.1</version>
98+
<version>3.0.0</version>
9999
</dependency>
100100
<dependency>
101101
<groupId>org.apache.pulsar</groupId>
102102
<artifactId>pulsar-client-admin</artifactId>
103-
<version>2.11.1</version>
103+
<version>3.0.0</version>
104104
</dependency>
105105

106106
</dependencies>

backend/src/main/java/de/amos/apachepulsarui/ApachePulsarUiApplication.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import org.springframework.boot.SpringApplication;
1010
import org.springframework.boot.autoconfigure.SpringBootApplication;
1111
import org.springframework.cache.annotation.EnableCaching;
12+
import org.springframework.context.annotation.Bean;
13+
import org.springframework.web.servlet.config.annotation.CorsRegistry;
14+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
1215

1316
@SpringBootApplication
1417
@EnableCaching
@@ -18,4 +21,14 @@ public static void main(String[] args) {
1821
SpringApplication.run(ApachePulsarUiApplication.class, args);
1922
}
2023

24+
@Bean
25+
public WebMvcConfigurer configurer() {
26+
return new WebMvcConfigurer() {
27+
@Override
28+
public void addCorsMappings(CorsRegistry corsRegistry) {
29+
corsRegistry.addMapping("/**").allowedOrigins("*");
30+
}
31+
};
32+
}
33+
2134
}

backend/src/main/java/de/amos/apachepulsarui/controller/TopicController.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66

77
package de.amos.apachepulsarui.controller;
88

9+
import de.amos.apachepulsarui.dto.ProducerDto;
10+
import de.amos.apachepulsarui.dto.SubscriptionDto;
911
import de.amos.apachepulsarui.dto.TopicDto;
1012
import de.amos.apachepulsarui.dto.TopicsDto;
13+
import de.amos.apachepulsarui.service.NamespaceService;
14+
import de.amos.apachepulsarui.service.TenantService;
1115
import de.amos.apachepulsarui.service.TopicService;
1216
import lombok.RequiredArgsConstructor;
1317
import org.apache.pulsar.common.naming.NamespaceName;
@@ -16,25 +20,51 @@
1620
import org.springframework.http.ResponseEntity;
1721
import org.springframework.web.bind.annotation.*;
1822

23+
import java.util.List;
24+
1925

2026
@RestController
2127
@RequiredArgsConstructor
2228
@RequestMapping("/topic")
2329
public class TopicController {
2430

31+
private final TenantService tenantService;
32+
private final NamespaceService namespaceService;
2533
private final TopicService topicService;
2634

35+
// Talked about this with Julian - probably we won't use it this way later, but at first it's easier for them
36+
// to just get all topics at once.
37+
@GetMapping("/all")
38+
public ResponseEntity<TopicsDto> getAll() {
39+
List<TopicDto> allTopics = tenantService.getAllTenants().stream()
40+
.flatMap(tenantDto -> namespaceService.getAllOfTenant(tenantDto).stream())
41+
.flatMap(namespaceDto -> topicService.getAllByNamespace(namespaceDto.getId()).stream())
42+
.toList();
43+
return new ResponseEntity<>(new TopicsDto(allTopics), HttpStatus.OK);
44+
}
45+
2746
@GetMapping("/{tenant}/{namespace}")
2847
public ResponseEntity<TopicsDto> getTopicsByNamespace(@PathVariable String namespace, @PathVariable String tenant) {
2948
String namespaceName = NamespaceName.get(tenant, namespace).toString();
3049
return new ResponseEntity<>(new TopicsDto(topicService.getAllByNamespace(namespaceName)), HttpStatus.OK);
3150
}
3251

33-
@GetMapping("/{topic}")
34-
public ResponseEntity<TopicDto> getTopicWithMessagesByName(@PathVariable String topic) {
35-
return new ResponseEntity<>(topicService.getTopicWithMessagesByName(topic), HttpStatus.OK);
52+
@GetMapping
53+
public ResponseEntity<TopicDto> getTopicWithMessagesByName(@RequestParam String name) {
54+
return new ResponseEntity<>(topicService.getTopicWithMessagesByName(name), HttpStatus.OK);
55+
}
56+
57+
@GetMapping("/subscription/{subscription}")
58+
public ResponseEntity<SubscriptionDto> getSubyscriptionByNameAndTopic(@RequestParam String topic, @PathVariable String subscription) {
59+
return new ResponseEntity<>(topicService.getSubscriptionByTopic(topic, subscription), HttpStatus.OK);
60+
}
61+
62+
@GetMapping("/producer/{producer}")
63+
public ResponseEntity<ProducerDto> getProducerByNameAndTopic(@RequestParam String topic, @PathVariable String producer) {
64+
return new ResponseEntity<>(topicService.getProducerByTopic(topic, producer), HttpStatus.OK);
3665
}
3766

67+
3868
@PostMapping("/new")
3969
public ResponseEntity<Void> newTopic(@RequestParam String topic) {
4070
if (!TopicName.isValid(topic)) {

backend/src/main/java/de/amos/apachepulsarui/dto/ConsumerDto.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class ConsumerDto {
1616

1717
private String name;
1818

19-
public static ConsumerDto createConsumerDto(ConsumerStats consumerStats) {
19+
public static ConsumerDto create(ConsumerStats consumerStats) {
2020
return ConsumerDto.builder().name(consumerStats.getConsumerName()).build();
2121
}
2222

backend/src/main/java/de/amos/apachepulsarui/dto/MessageDto.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public class MessageDto {
3535

3636
Long publishTime;
3737

38+
String producer;
39+
3840
/**
3941
* Static factory for messages already existing in Pulsar.
4042
*/
@@ -48,6 +50,7 @@ public static MessageDto fromExistingMessage(Message<byte[]> message, String sch
4850
messageDto.namespace = TopicName.get(topicName).getNamespacePortion();
4951
messageDto.tenant = TopicName.get(topicName).getTenant();
5052
messageDto.publishTime = message.getPublishTime();
53+
messageDto.producer = message.getProducerName();
5154

5255
return messageDto;
5356
}

backend/src/main/java/de/amos/apachepulsarui/dto/ProducerDto.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,27 @@
55

66
package de.amos.apachepulsarui.dto;
77

8-
import lombok.AccessLevel;
9-
import lombok.Builder;
10-
import lombok.Data;
8+
import lombok.*;
119
import org.apache.pulsar.common.policies.data.PublisherStats;
1210

11+
import java.util.List;
12+
1313
@Data
14+
@AllArgsConstructor
1415
@Builder(access = AccessLevel.PRIVATE)
1516
public class ProducerDto {
1617

1718
private String name;
1819

19-
public static ProducerDto createProducerDto(PublisherStats publisherStats) {
20-
return ProducerDto.builder().name(publisherStats.getProducerName()).build();
20+
private List<MessageDto> messagesDto;
21+
22+
private long amountOfMessages;
23+
24+
public static ProducerDto create(PublisherStats publisherStats, List<MessageDto> messages) {
25+
return ProducerDto.builder()
26+
.name(publisherStats.getProducerName())
27+
.messagesDto(messages)
28+
.amountOfMessages(messages.size())
29+
.build();
2130
}
2231
}

backend/src/main/java/de/amos/apachepulsarui/dto/SubscriptionDto.java

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,55 @@
88
import lombok.AccessLevel;
99
import lombok.Builder;
1010
import lombok.Data;
11+
import org.apache.pulsar.common.policies.data.SubscriptionStats;
1112

1213
import java.util.List;
14+
import java.util.Objects;
1315

1416
@Data
1517
@Builder(access = AccessLevel.PRIVATE)
1618
public class SubscriptionDto {
1719

1820
private String name;
1921

20-
private List<ConsumerDto> consumers;
22+
private ConsumerDto activeConsumer;
23+
24+
private List<ConsumerDto> allConsumers;
25+
26+
private List<MessageDto> messages;
2127

2228
private long numberConsumers;
2329

24-
public static SubscriptionDto createSubscriptionDto(String name, List<ConsumerDto> consumers) {
30+
private double msgAckRate;
31+
32+
private long msgBacklog;
33+
34+
private long msgOutCounter;
35+
36+
public static SubscriptionDto create(SubscriptionStats subscriptionStats, List<MessageDto> messages, String name) {
37+
List<ConsumerDto> consumers = getConsumers(subscriptionStats);
38+
ConsumerDto active = consumers
39+
.stream()
40+
.filter(c -> Objects.equals(c.getName(), subscriptionStats.getActiveConsumerName()))
41+
.findFirst()
42+
.orElse(null);
43+
2544
return SubscriptionDto.builder()
2645
.name(name)
27-
.consumers(consumers)
28-
.numberConsumers(consumers.size())
46+
.messages(messages)
47+
.activeConsumer(active)
48+
.allConsumers(consumers)
49+
.msgAckRate(subscriptionStats.getMessageAckRate())
50+
.msgBacklog(subscriptionStats.getMsgBacklog())
51+
.msgOutCounter(builder().msgOutCounter)
2952
.build();
3053
}
54+
55+
private static List<ConsumerDto> getConsumers(SubscriptionStats subscriptionStats) {
56+
return subscriptionStats.getConsumers()
57+
.stream()
58+
.map(ConsumerDto::create)
59+
.toList();
60+
61+
}
3162
}

backend/src/main/java/de/amos/apachepulsarui/dto/TopicStatsDto.java

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,18 @@
88
import lombok.AccessLevel;
99
import lombok.Builder;
1010
import lombok.Data;
11-
import org.apache.pulsar.common.policies.data.ConsumerStats;
1211
import org.apache.pulsar.common.policies.data.PublisherStats;
13-
import org.apache.pulsar.common.policies.data.SubscriptionStats;
1412
import org.apache.pulsar.common.policies.data.TopicStats;
1513

1614
import java.util.ArrayList;
17-
import java.util.HashMap;
1815
import java.util.List;
19-
import java.util.Map;
16+
import java.util.Set;
2017

2118
@Data
2219
@Builder(access = AccessLevel.PRIVATE)
2320
public class TopicStatsDto {
2421

25-
private List<String> subscriptions;
22+
private Set<String> subscriptions;
2623

2724
private List<String> producers;
2825

@@ -39,7 +36,8 @@ public class TopicStatsDto {
3936
private long storageSize;
4037

4138
public static TopicStatsDto createTopicStatsDto(TopicStats topicStats) {
42-
List<String> subscriptions = getSubscriptions(topicStats);
39+
40+
Set<String> subscriptions = topicStats.getSubscriptions().keySet();
4341
List<String> producers = getProducers(topicStats);
4442

4543
return TopicStatsDto.builder()
@@ -55,27 +53,16 @@ public static TopicStatsDto createTopicStatsDto(TopicStats topicStats) {
5553

5654
}
5755

58-
private static List<String> getProducers(TopicStats topicStats) {
56+
public static List<String> getProducers(TopicStats topicStats) {
5957
List<PublisherStats> publisherStats = new ArrayList<>(topicStats.getPublishers());
6058
return publisherStats.stream()
6159
.map(PublisherStats::getProducerName)
6260
.toList();
6361
}
6462

65-
private static List<String> getSubscriptions(TopicStats topicStats) {
66-
Map<String, SubscriptionStats> subscriptionStats = new HashMap<>(topicStats.getSubscriptions());
67-
List<String> subscriptions = new ArrayList<>();
68-
subscriptionStats.forEach((name, producers) -> subscriptions.add(name));
69-
return subscriptions;
70-
}
7163

72-
private static List<ConsumerDto> getConsumers(SubscriptionStats subscriptionStats) {
73-
List<ConsumerStats> consumerStats = new ArrayList<>(subscriptionStats.getConsumers());
74-
return consumerStats
75-
.stream()
76-
.map(ConsumerDto::createConsumerDto)
77-
.toList();
78-
}
64+
65+
7966

8067

8168
}

0 commit comments

Comments
 (0)