Optimized bucket list response

This commit is contained in:
Andrey Terentev 2023-12-04 11:40:04 +07:00
parent 355983b764
commit 070068aecc
10 changed files with 60 additions and 36 deletions

View File

@ -16,7 +16,7 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.component.textfield.TextField;
import lombok.Setter; import lombok.Setter;
import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.dto.BucketDTO;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -24,12 +24,12 @@ import java.util.function.Consumer;
public class BucketList extends VerticalLayout { public class BucketList extends VerticalLayout {
private final String nodeIdentifier; private final String nodeIdentifier;
private final Grid<Bucket> bucketsGrid; private final Grid<BucketDTO> bucketsGrid;
private final TextField searchField; private final TextField searchField;
private List<Bucket> cachedBuckets; private List<BucketDTO> cachedBuckets;
@Setter private Consumer<Bucket> removeMethod; @Setter private Consumer<BucketDTO> removeMethod;
public BucketList(String nodeIdentifier, List<Bucket> buckets) { public BucketList(String nodeIdentifier, List<BucketDTO> buckets) {
this.nodeIdentifier = nodeIdentifier; this.nodeIdentifier = nodeIdentifier;
cachedBuckets = buckets; cachedBuckets = buckets;
@ -53,26 +53,26 @@ public class BucketList extends VerticalLayout {
var temp = input.trim(); var temp = input.trim();
bucketsGrid.setItems(cachedBuckets.stream() bucketsGrid.setItems(cachedBuckets.stream()
.filter(bucket -> bucket.getIdentifier().startsWith(temp)) .filter(bucket -> bucket.identifier().startsWith(temp))
.toList()); .toList());
} }
private Grid<Bucket> createGrid() { private Grid<BucketDTO> createGrid() {
var grid = new Grid<>(Bucket.class, false); var grid = new Grid<>(BucketDTO.class, false);
grid.addColumn(Bucket::getIdentifier).setHeader("Identifier"); grid.addColumn(BucketDTO::identifier).setHeader("Identifier");
grid.addComponentColumn(bucket -> { grid.addComponentColumn(bucket -> {
var result = new Span(); var result = new Span();
if (bucket.getSlots().isUnlimited()) { if (bucket.slots() == -1) {
result.setText("Unlimited"); result.setText("Unlimited");
result.getElement().getThemeList().add("badge contrast"); result.getElement().getThemeList().add("badge contrast");
} else { } else {
result.setText(Integer.toString(bucket.getSlots().slots())); result.setText(Integer.toString(bucket.slots()));
} }
return result; return result;
}).setHeader("Slots").setTextAlign(ColumnTextAlign.CENTER); }).setHeader("Slots").setTextAlign(ColumnTextAlign.CENTER);
grid.addComponentColumn(bucket -> { grid.addComponentColumn(bucket -> {
var result = new Span(); var result = new Span();
if (bucket.isLocked()) { if (bucket.locked()) {
result.setText("Yes"); result.setText("Yes");
result.getElement().getThemeList().add("badge error"); result.getElement().getThemeList().add("badge error");
} else { } else {
@ -84,7 +84,7 @@ public class BucketList extends VerticalLayout {
return grid; return grid;
} }
private HorizontalLayout createManageButtons(Bucket bucket) { private HorizontalLayout createManageButtons(BucketDTO bucket) {
var layout = new HorizontalLayout(); var layout = new HorizontalLayout();
{ {
@ -104,16 +104,16 @@ public class BucketList extends VerticalLayout {
return layout; return layout;
} }
private void clickDetailsButton(Bucket bucket) { private void clickDetailsButton(BucketDTO bucket) {
getUI().ifPresent(ui -> { getUI().ifPresent(ui -> {
ui.navigate("/nodes/" + nodeIdentifier + ui.navigate("/nodes/" + nodeIdentifier +
"/buckets/" + bucket.getIdentifier()); "/buckets/" + bucket.identifier());
}); });
} }
private void clickRemoveButton(Bucket bucket) { private void clickRemoveButton(BucketDTO bucket) {
var dialog = new Dialog("Confirm bucket deletion"); var dialog = new Dialog("Confirm bucket deletion");
dialog.add(new Paragraph("Confirm that you want to delete bucket. Enter '" + bucket.getIdentifier() + "' to field below and confirm.")); dialog.add(new Paragraph("Confirm that you want to delete bucket. Enter '" + bucket.identifier() + "' to field below and confirm."));
var inputField = new TextField(); var inputField = new TextField();
dialog.add(inputField); dialog.add(inputField);
@ -122,14 +122,14 @@ public class BucketList extends VerticalLayout {
var button = new Button("Confirm"); var button = new Button("Confirm");
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
button.addClickListener(event -> { button.addClickListener(event -> {
if (!bucket.getIdentifier().equals(inputField.getValue())) { if (!bucket.identifier().equals(inputField.getValue())) {
Notification.show("Invalid input", 3000, Notification.Position.TOP_END) Notification.show("Invalid input", 3000, Notification.Position.TOP_END)
.addThemeVariants(NotificationVariant.LUMO_ERROR); .addThemeVariants(NotificationVariant.LUMO_ERROR);
return; return;
} }
removeBucket(bucket); removeBucket(bucket);
Notification.show("Bucket '" + bucket.getIdentifier() + "' was successfully removed!", 3000, Notification.Position.TOP_END) Notification.show("Bucket '" + bucket.identifier() + "' was successfully removed!", 3000, Notification.Position.TOP_END)
.addThemeVariants(NotificationVariant.LUMO_SUCCESS); .addThemeVariants(NotificationVariant.LUMO_SUCCESS);
dialog.close(); dialog.close();
}); });
@ -146,12 +146,12 @@ public class BucketList extends VerticalLayout {
dialog.open(); dialog.open();
} }
public void update(List<Bucket> buckets) { public void update(List<BucketDTO> buckets) {
cachedBuckets = buckets; cachedBuckets = buckets;
applySearch(searchField.getValue()); applySearch(searchField.getValue());
} }
private void removeBucket(Bucket bucket) { private void removeBucket(BucketDTO bucket) {
if (removeMethod != null) { if (removeMethod != null) {
removeMethod.accept(bucket); removeMethod.accept(bucket);
} }

View File

@ -0,0 +1,16 @@
package ru.dragonestia.loadbalancer.web.model.dto;
import ru.dragonestia.loadbalancer.web.model.Node;
import java.net.URI;
public record BucketDTO(String identifier, int slots, boolean locked) {
public URI uriAPI(Node node) {
return uriAPI(node.identifier());
}
public URI uriAPI(String nodeId) {
return URI.create("/nodes/" + nodeId + "/buckets/" + identifier);
}
}

View File

@ -3,7 +3,6 @@ package ru.dragonestia.loadbalancer.web.page;
import com.vaadin.flow.component.Html; import com.vaadin.flow.component.Html;
import com.vaadin.flow.component.Unit; import com.vaadin.flow.component.Unit;
import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Hr; import com.vaadin.flow.component.html.Hr;
import com.vaadin.flow.component.html.Paragraph; import com.vaadin.flow.component.html.Paragraph;

View File

@ -16,10 +16,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import ru.dragonestia.loadbalancer.web.component.BucketList; import ru.dragonestia.loadbalancer.web.component.BucketList;
import ru.dragonestia.loadbalancer.web.component.NavPath; import ru.dragonestia.loadbalancer.web.component.NavPath;
import ru.dragonestia.loadbalancer.web.component.RegisterBucket; import ru.dragonestia.loadbalancer.web.component.RegisterBucket;
import ru.dragonestia.loadbalancer.web.model.Bucket;
import ru.dragonestia.loadbalancer.web.model.Node; import ru.dragonestia.loadbalancer.web.model.Node;
import ru.dragonestia.loadbalancer.web.model.type.LoadBalancingMethod; import ru.dragonestia.loadbalancer.web.model.dto.BucketDTO;
import ru.dragonestia.loadbalancer.web.model.type.SlotLimit;
import ru.dragonestia.loadbalancer.web.repository.BucketRepository; import ru.dragonestia.loadbalancer.web.repository.BucketRepository;
import ru.dragonestia.loadbalancer.web.repository.NodeRepository; import ru.dragonestia.loadbalancer.web.repository.NodeRepository;
@ -66,7 +64,7 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv
initComponents(node, bucketRepository.all(node)); initComponents(node, bucketRepository.all(node));
} }
private void initComponents(Node node, List<Bucket> buckets) { private void initComponents(Node node, List<BucketDTO> buckets) {
printNodeDetails(node); printNodeDetails(node);
add(new Hr()); add(new Hr());
add(registerBucket = new RegisterBucket(node, (bucket) -> { add(registerBucket = new RegisterBucket(node, (bucket) -> {
@ -82,7 +80,7 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv
add(new Hr()); add(new Hr());
add(bucketList = new BucketList(node.identifier(), buckets)); add(bucketList = new BucketList(node.identifier(), buckets));
bucketList.setRemoveMethod(bucket -> { bucketList.setRemoveMethod(bucket -> {
bucketRepository.remove(bucket); bucketRepository.remove(node, bucket);
bucketList.update(bucketRepository.all(node)); bucketList.update(bucketRepository.all(node));
}); });
} }

View File

@ -7,7 +7,6 @@ import com.vaadin.flow.router.Route;
import lombok.Getter; import lombok.Getter;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;
import ru.dragonestia.loadbalancer.web.component.NavPath; import ru.dragonestia.loadbalancer.web.component.NavPath;
import ru.dragonestia.loadbalancer.web.component.NodeList; import ru.dragonestia.loadbalancer.web.component.NodeList;
import ru.dragonestia.loadbalancer.web.component.RegisterNode; import ru.dragonestia.loadbalancer.web.component.RegisterNode;

View File

@ -2,18 +2,21 @@ package ru.dragonestia.loadbalancer.web.repository;
import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.Bucket;
import ru.dragonestia.loadbalancer.web.model.Node; import ru.dragonestia.loadbalancer.web.model.Node;
import ru.dragonestia.loadbalancer.web.model.dto.BucketDTO;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
public interface BucketRepository { public interface BucketRepository {
List<Bucket> all(Node node); List<BucketDTO> all(Node node);
void register(Bucket bucket); void register(Bucket bucket);
void remove(Bucket bucket); void remove(Bucket bucket);
void remove(Node node, BucketDTO bucket);
Optional<Bucket> find(Node node, String identifier); Optional<Bucket> find(Node node, String identifier);
void lock(Bucket bucket, boolean value); void lock(Bucket bucket, boolean value);

View File

@ -6,6 +6,7 @@ import lombok.extern.log4j.Log4j2;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.Bucket;
import ru.dragonestia.loadbalancer.web.model.Node; import ru.dragonestia.loadbalancer.web.model.Node;
import ru.dragonestia.loadbalancer.web.model.dto.BucketDTO;
import ru.dragonestia.loadbalancer.web.repository.BucketRepository; import ru.dragonestia.loadbalancer.web.repository.BucketRepository;
import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketInfoResponse; import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketInfoResponse;
import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketListResponse; import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketListResponse;
@ -24,7 +25,7 @@ public class BucketRepositoryImpl implements BucketRepository {
private final RestUtil rest; private final RestUtil rest;
@Override @Override
public List<Bucket> all(Node node) { public List<BucketDTO> all(Node node) {
var entity = rest.getEntity(URI.create("/nodes/" + node.identifier() + "/buckets"), var entity = rest.getEntity(URI.create("/nodes/" + node.identifier() + "/buckets"),
BucketListResponse.class); BucketListResponse.class);
@ -70,6 +71,11 @@ public class BucketRepositoryImpl implements BucketRepository {
rest.delete(URI.create("/nodes/" + bucket.getNodeIdentifier() + "/buckets/" + bucket.getIdentifier()), params -> {}); rest.delete(URI.create("/nodes/" + bucket.getNodeIdentifier() + "/buckets/" + bucket.getIdentifier()), params -> {});
} }
@Override
public void remove(Node node, BucketDTO bucket) {
rest.delete(URI.create("/nodes/" + node.identifier() + "/buckets/" + bucket.identifier()), params -> {});
}
@Override @Override
public Optional<Bucket> find(Node node, String identifier) { public Optional<Bucket> find(Node node, String identifier) {
try { try {

View File

@ -1,7 +1,7 @@
package ru.dragonestia.loadbalancer.web.repository.impl.response; package ru.dragonestia.loadbalancer.web.repository.impl.response;
import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.dto.BucketDTO;
import java.util.List; import java.util.List;
public record BucketListResponse(String node, List<Bucket> buckets) {} public record BucketListResponse(String node, List<BucketDTO> buckets) {}

View File

@ -28,7 +28,9 @@ public class BucketController {
ResponseEntity<BucketListResponse> allBuckets(@PathVariable(name = "nodeIdentifier") String nodeId) { ResponseEntity<BucketListResponse> allBuckets(@PathVariable(name = "nodeIdentifier") String nodeId) {
var nodeOpt = nodeService.findNode(nodeId); var nodeOpt = nodeService.findNode(nodeId);
return nodeOpt.map(node -> ResponseEntity.ok(new BucketListResponse(nodeId, return nodeOpt.map(node -> ResponseEntity.ok(new BucketListResponse(nodeId,
bucketService.allBuckets(node).stream().toList() bucketService.allBuckets(node).stream()
.map(bucket -> new BucketListResponse.BucketDTO(bucket.getIdentifier(), bucket.getSlots().getSlots(), bucket.isLocked()))
.toList()
))).orElseGet(() -> ResponseEntity.notFound().build()); ))).orElseGet(() -> ResponseEntity.notFound().build());
} }

View File

@ -1,7 +1,8 @@
package ru.dragonestia.loadbalancer.controller.response; package ru.dragonestia.loadbalancer.controller.response;
import ru.dragonestia.loadbalancer.model.Bucket;
import java.util.List; import java.util.List;
public record BucketListResponse(String node, List<Bucket> buckets) {} public record BucketListResponse(String node, List<BucketDTO> buckets) {
public record BucketDTO(String identifier, int slots, boolean locked) {}
}